Handlebars - helper

Why oh why does Ghost not use GitHub - helpers/handlebars-helpers: 188 handlebars helpers in ~20 categories. Can be used with Assemble, Ghost, YUI, express.js etc. by default?

There are so many good helpers there that would make life easy when theming…

Is it possible to use these handlebars-helper someway or another?

Thanks,
Ronald

3 Likes

Hi Ronald,

If you are into development, the area of the code which needs to be looked into to integrate these helpers is under core/frontend in the main Ghost directory (GitHub - TryGhost/Ghost: Turn your audience into a business. Publishing, memberships, subscriptions and newsletters.).

Good luck.

Cheers,
Alex.

I know this is an old one but I’m another vote for this! It would just make doing little custom things in the theme’s so much easier to have these.

I wish this had been added to the ideas forum so it could have been voted on. Maybe it can be moved there?

Same thing, its a bit of an old topic, but since its not detailed in the documentation, here’s a way to do it.
First, yarn add handlebars-helpers inside the current directory (or versions/X.Y.Z).
Then, edit the handlebar wrapper engine :
current/core/frontend/services/themes/engine.js:l5

const helpers = require('handlebars-helpers')()
instance.handlebars.helpers = {
    ...instance.handlebars.helpers,
    startsWith: helpers.startsWith,              <~~ New helpers here
    eq: helpers.eq,
}

Since the gscan theme validation checks the helpers, they should also be added here :
current/node_modules/gscan/lib/specs/v1.js:18

knownHelpers = [
    (…some helpers…)

    'startsWith', 'eq',          <~~ New helpers here

    // Handlebars and express handlebars
    'log', 'if', 'unless', 'with', 'block', 'contentFor', 'each', 'lookup'
];

In these examples, I included startsWith and eq (which I needed to create a navigation submenu). However some handlebars-helpers might conflict with the ones created by the Ghost team.

Of course, since these changes alter the core and node_modules, it has to be done again at each upgrade / install / deployment, until those helpers eventually make it to Ghost core. Maybe the devs could one day allow (via an entry in the config json), a selection amongst the ones in handlebars-helpers ?

2 Likes

This has pointed me somewhat in the right direction for something I’m working on, however between April and now I think there have been some changes to how ghost handles helpers, and it’s causing some problems. I’m using 4.11 and this is what I’ve gathered:

  • Engine.js folder has moved from current/core/frontend/services/themes/engine.js to current/core/frontend/services/theme-engine/engine.js
  • There’s a current/core/frontend/helpers/ folder and it appears the index.js file in there iterates through all .js files in there and packages all files there as new helper commands that the engine registers as new helpers (with filename being the handlebars helper command)

My issue is that I have written a helper that I know works from testing on the handlebars website, I have added the following menu.js file into the helpers folder:

const {SafeString} = require('../services/proxy');

module.exports = function menu(nav) {
	var text = "";
  	let map = [];
  	let key = [];
  	for (let x in nav) {
  		map.push(nav[x].title);
    	key.push(x);
  	}
  	for (let x in map) {
  		let curr = [map[x],""];
    	let y = Number(x) + 1;
    	var next;
    	if (map[y] != undefined) {
      		next = map[y];
    	} else {
      		next = "";
  		}
    	if (next.startsWith("- ") && !curr[0].startsWith("- ")) {
    		text += "  <li>" + nav[key[x]].title + "\n    <ul class='parent'>\n";
    	} else if (curr[0].startsWith("- ") && next.startsWith("- ")) {
    		text += "      <li>" + nav[key[x]].title.slice(2) + "</li>\n";
    	} else if (curr[0].startsWith("- ") && !next.startsWith("- ")) {
    		text += "      <li>" + nav[key[x]].title.slice(2) + "</li>\n    </ul>\n  </li>\n";
    	} else {
    		text += "  <li>" + nav[key[x]].title + "</li>\n";
    	}
  	}
  	return new SafeString(text);
};

(it’s awaiting refinement, I just want it to work before I refine it), there’s nowhere to add the const helpers = require.... code in the engine.js file that I can see (since things seem to have changed) and I have added the helper to gscan. I have restarted the ghost and the whole server, but it’s saying the helper ‘menu’ doesn’t exist. I would add the handlebars-helpers like in this suggestion, to handle the menu system in handlebars, but I also can’t get this to work either since the current engine.js has nowhere to add new helpers since it iterates through all files in the helper folder. If there something I’m overlooking?

You can look at the code in theme-engine/index.js where it references loadCoreHelpers function
loadCoreHelpers: require('./handlebars/helpers').loadCoreHelpers,
And from there you can see where it’s loading all helpers.

As for your custom helpers, I believe you need to load them from core (inject your own code) with code like :

const hbs = require('../../theme-engine/engine');  // Depends on where you are loading from
hbs.registerHelper({Given Name}, require({Helper File}));    // Replace name and file with yours

Since you are modifying core, be careful to put it back any time you update Ghost and it is removed.

At some point, for a POC, I wrote a function to automatically add all helpers from a subdirectory within content folder, so they would not be overwritten. Then I was able to reference these helpers from the themes. That was way back (I believe v4.1), so I may have to revisit that if core files have changed