Skip to content

Instantly share code, notes, and snippets.

@ofstudio
Last active September 9, 2021 09:55
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save ofstudio/e13276a9c587ecd41a95 to your computer and use it in GitHub Desktop.
Save ofstudio/e13276a9c587ecd41a95 to your computer and use it in GitHub Desktop.
Couple useful heplers for ghost
var hbs = require('express-hbs'),
api = require('core/server/api'),
_ = require('lodash'),
async = require('express-hbs/lib/async'), // To redefine `registerAsyncHelper`
registerAsyncHelper;
// Redefine `registerAsyncHelper` from `express-hbs`
registerAsyncHelper = function (name, fn) {
hbs.handlebars.registerHelper(name, function (context, options) {
// Pass `[context, options]` as arg instead of `context` only
return async.resolve(fn.bind(this), [context, options]);
});
};
module.exports = function () {
// {{#node_env}} Helper
//
// Example:
// {{#node_env production}}
// ...production only
// {{/node_env}}
//
hbs.registerHelper('node_env', function (env, options) {
return (options.data.root.settings.env === env) ? options.fn(this) : options.inverse(this)
});
// {{#by_tag}} Helper
//
// Example:
// {{#by_tag 'dev'}}
// {{#foreach posts}}
// {{title}}
// {{content}}
// {{/foreach}}
// {{/by_tag}}
//
// TODO `page` or smth like this functionality
//
registerAsyncHelper('by_tag', function (context_data, callback) {
var context = context_data[0], // get context and options passed from context_data array
options = context_data[1],
parameters = (options || {}).hash || {},
request = {
context: {internal: true},
tag: context
};
if (parameters.hasOwnProperty('limit')) {
request.limit = parameters.limit
}
return api.posts.browse(request).then(function (responce) {
var data;
if (options !== undefined && typeof options.fn === 'function') {
data = hbs.handlebars.createFrame(options.data || {});
data.posts = responce.posts;
console.log(data);
callback(options.fn(data))
} else {
callback('')
}
});
});
// {{{hello_kitty}}} Sample Helper
hbs.registerHelper('hello_kitty', function () {
return new hbs.handlebars.SafeString('Hello =^oo^= Kitty!');
});
};
@ofstudio
Copy link
Author

Useful heplers for ghost

Tested with Ghost 0.5.8

Installation

  1. Create helpers.js in ghost directory (code above)
  2. Add first line to your config.js: require('./helpers')();
  3. Restart ghost

Usage

Use this helpers in your Ghost theme files

{{#node_env}} Helper

Example:

{{#node_env production}}
     ...production only 
{{/node_env}}

{{#by_tag}} Helper

Select posts by tag. Optional limit parameter.

Example:

 {{#by_tag 'dev'}}
     {{#foreach posts}}
         {{title}}
         {{content}}
     {{/foreach}}
 {{/by_tag}}
 {{#by_tag 'music' limit=3}}
     {{#foreach posts}}
         {{title}}
         {{content}}
     {{/foreach}}
 {{/by_tag}}

@mordeng
Copy link

mordeng commented Mar 31, 2015

hey,
did 0.5.10 break it?
i cant start the ghost server..

edit: seems like dependencies are not met...maybe some files change location?

./ before every path made it work

@GenericUK
Copy link

Hi, any thoughts on getting this to work with Handlebars reverse option
{{^by_tag 'dev'}}
show post without tag dev
{{/by_tag}}

@hashworks-India
Copy link

{{#by_tag}} works fine.But if used twice like.

{{#by_tag 'tag1'}}
//do something
{{/by_tag}}

{{#by_tag 'tag2'}}
//do something
{{/by_tag}}

throws the following error in the server.Please help

ERROR: Can't set headers after they are sent.
registerAsyncThemeHelper: ghost_head

Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (C:\Ghost\ghost-0.7.1\node_modules\express\lib\response.js:700:10)
at ServerResponse.send (C:\Ghost\ghost-0.7.1\node_modules\express\lib\response.js:154:12)
at fn (C:\Ghost\ghost-0.7.1\node_modules\express\lib\response.js:934:10)
at _stackRenderer (C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\hbs.js:524:9)
at Waiter.callback (C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\hbs.js:501:7)
at Waiter.resolve (C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\async.js:43:12)
at C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\async.js:84:15
at C:\Ghost\ghost-0.7.1\core\server\helpers\index.js:64:13
at tryCatcher (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\util.js:24:31)
at Promise._settlePromiseFromHandler (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\promise.js:454:31)
at Promise._settlePromiseAt (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\promise.js:530:18)
at Promise._settlePromises (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\promise.js:646:14)
at Async._drainQueue (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\async.js:177:16)
at Async._drainQueues (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\async.js:187:10)
at Immediate.Async.drainQueues as _onImmediate
at processImmediate as _immediateCallback

Unhandled rejection Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (C:\Ghost\ghost-0.7.1\node_modules\express\lib\response.js:700:10)
at ServerResponse.send (C:\Ghost\ghost-0.7.1\node_modules\express\lib\response.js:154:12)
at fn (C:\Ghost\ghost-0.7.1\node_modules\express\lib\response.js:934:10)
at _stackRenderer (C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\hbs.js:524:9)
at Waiter.callback (C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\hbs.js:501:7)
at Waiter.resolve (C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\async.js:43:12)
at C:\Ghost\ghost-0.7.1\node_modules\express-hbs\lib\async.js:84:15
at C:\Ghost\ghost-0.7.1\core\server\helpers\index.js:64:13
at tryCatcher (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\util.js:24:31)
at Promise._settlePromiseFromHandler (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\promise.js:454:31)
at Promise._settlePromiseAt (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\promise.js:530:18)
at Promise._settlePromises (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\promise.js:646:14)
at Async._drainQueue (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\async.js:177:16)
at Async._drainQueues (C:\Ghost\ghost-0.7.1\node_modules\bluebird\js\main\async.js:187:10)
at Immediate.Async.drainQueues as _onImmediate
at processImmediate as _immediateCallback

@henrytao-me
Copy link

This code is compatible with ghost 0.7.4 and support multiple tags.

var hbs = require('express-hbs'),
  api = require('./core/server/api'),
  _ = require('lodash'),
  async = require('express-hbs/lib/async'), // To redefine `registerAsyncHelper`
  registerAsyncHelper;

// Redefine `registerAsyncHelper` from `express-hbs`
registerAsyncHelper = function(name, fn) {
  hbs.handlebars.registerHelper(name, function(context, options) {
    // Pass `[context, options]` as arg instead of `context` only
    return async.resolve(fn.bind(this), [context, options]);
  });
};

module.exports = function() {

  // {{#by_tag}} Helper
  //
  // Example:
  // {{#by_tag 'dev,prod' limit=3}}
  //    {{#foreach posts}}
  //        {{title}}
  //        {{content}}
  //    {{/foreach}}
  // {{/by_tag}}
  //
  // TODO `page` or smth like this functionality
  //
  registerAsyncHelper('by_tag', function(context_data, callback) {
    var context = context_data[0], // get context and options passed from context_data array
      options = context_data[1],
      parameters = (options || {}).hash || {},
      request = {
        context: {
          internal: true
        }
      };

    var tags = (context || '').split(',');
    _.each(tags, function(tag, i) {
      tags[i] = 'tag:' + tags[i];
    });
    if (tags.length > 0) {
      request.filter = tags.join(',');
    }

    if (parameters.hasOwnProperty('limit')) {
      request.limit = parameters.limit
    }

    return api.posts.browse(request).then(function(responce) {
      var data;
      if (options !== undefined && typeof options.fn === 'function') {
        data = hbs.handlebars.createFrame(options.data || {});
        data.posts = responce.posts;
        data.pagination = {
          page: 1,
          prev: 0,
          next: 0,
          pages: 1,
          total: request.limit || 100,
          limit: request.limit || 100
        };
        callback(options.fn(data))
      } else {
        callback('')
      }
    });
  });
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment