pcardune / handlebars-loader

A handlebars template loader for webpack
551 stars 168 forks source link

how to user handlebars-loader with handlebars-helpers #110

Open Shpiller opened 7 years ago

Shpiller commented 7 years ago

handlebars-helpers link https://github.com/assemble/handlebars-helpers

mAAdhaTTah commented 7 years ago

Set knownHelpersOnly to false and register the helpers at runtime the old-fashioned way.

mAAdhaTTah commented 7 years ago
var Handlebars = require('handlebars/runtime');

Handlebars.registerHelper('myHelper', myHelperFunction);
mAAdhaTTah commented 7 years ago

The Handlebars documentation has more info.

villeristi commented 7 years ago

@mAAdhaTTah some example would be nice, cheers.

mAAdhaTTah commented 7 years ago

@villeristi @sidonaldson I gave an example above. The helpers linked appear to register themselves with the Handlebars runtime, if you pass your own instance. There isn't anything webpack-specific going on here. The above example would go in your application code.

phoenixbox commented 7 years ago

@villeristi heres an example of what I used recently to set my google maps api key per environment.

https://gist.github.com/phoenixbox/d095d29fc09792ae4f51bf5f60aadd06

any questions let me know 👍

sidonaldson commented 7 years ago

@villeristi how do you use handlebars-loader with handlebars-helpers in webpack?

gregholland commented 7 years ago

I can't get this to work. WebPack compiles the handlebars template, then when my application is run registerHelper is called, but it's too late as the template is already compiled. Where am I going wrong?

craigmulligan commented 7 years ago

@phoenixbox you're example doesn't seem to use handlebars-helpers?

I've tried registering with the handlebars/runtime

require('handlebars-helpers')({
  handlebars: require('handlebars/runtime')
});

But webpack throws a bunch of errors aliasing explained here

Anyone had any luck with this?

craigmulligan commented 7 years ago

Hey All,

So I managed to register helpers individually by forking and then altering the export from the loader.

This is how I did it.

var helpers = require('handlebars-helpers')();

      // export as module if template is not blank
      var slug = template ?
        'var Handlebars = require(' + JSON.stringify(runtimePath) + ');\n'
        + 'Handlebars.registerHelper("capitalize", ' + helpers.capitalize + ');\n'

Still figuring out how to register them all at once, problem is we you can't JSON.stringify an all the methods as they lose scope.

@mAAdhaTTah any idea on how to go about this?

mAAdhaTTah commented 7 years ago

Best guess is to use webpack to alias handlebars/runtime to the path to the CJS instance of the runtime.

mAAdhaTTah commented 7 years ago

Hi everyone,

I got an email from someone about this issue recently. After going back and forth for a bit, the way we solved it was to specific the loader's options.runtime to match the handlebars/runtime alias, so that when you import hbs from 'handlebars/runtime';, hbs is the same Handlebars environment as the one used by your application code.

imo we should probably not be using require.resolve at all in the loader, and should just default to handlebars/runtime, which moves it from node's require resolution algo into webpack's, which is then subject to the resolve.alias rules.

astorije commented 6 years ago

Hey there!

Has anyone actually been able to solve this? I'd be curious to see some working configuration, not sure how to integrate with this Webpack config for now.

Thanks!

kimyu92 commented 6 years ago

@mAAdhaTTah mind to share your webpack config?

mAAdhaTTah commented 6 years ago

Best example I have public is here and I register the helpers here. Note that, in this case, I also have aliases for handlebars & handlebars/runtime. The reason for this is the test file is intended to run both in Node with Mocha as well as a browser with Mocha + Karma, and Handlebars behaves slightly differently depending on whether it's running in Node vs. Browser (it modifies node to allow you to require files with .hbs extensions).

This may be a bit complicated for the use case here, but should give you an idea of what you might need to do to to get external helpers working. Also note that I'm not sure the knownHelpers key is necessary, but once I got it working, I didn't change it.

kimyu92 commented 6 years ago

@mAAdhaTTah I get passed a lot of error based on your example, I would be nice if we don't have to do this at all and able to call those helpers on .hbs file

hbs.registerHelper('blackbox', attr => new hbs.SafeString(blackboxAttribute(attr)));
hbs.registerHelper('container', attr => new hbs.SafeString(containerAttribute(attr)));
hbs.registerHelper('key', attr => new hbs.SafeString(keyAttribute(attr)));
hbs.registerHelper('event', (...args) => new hbs.SafeString(eventAttribute(...args)));
mAAdhaTTah commented 6 years ago

Unfortunately, you can't really get around that. You have to either write a helper file for every helper you want to register with the loader, or you have to manually register helpers at runtime. I think that's the best we can do.

kimyu92 commented 6 years ago

@pcardune any idea how we can contribute to handlebars loader to support handlebars-helpers so that there is a path way to use those helpers without so much hassles like what @mAAdhaTTah suggested above?

pcardune commented 6 years ago

@kimyu92 best way to contribute is to submit a pull request! I actually don't use handlebars-loader myself anymore and am just here to review PRs and publish new releases. If anyone would like to help with that I can give you write access to this repo and the npm package.

mAAdhaTTah commented 6 years ago

@kimyu92 The bigger problem is you may not be able to set up integration with a package like handlebars-helper in a generic enough way to integrate with other helper libraries, unless all of them work the same way.

kimyu92 commented 6 years ago

sounds like what i could do is to port the whole handlebars helpers that complement with this loader so that people can easily use them by pointing to the dir

davedub commented 6 years ago

@mAAdhaTTah Where do you register the helpers so that the loader sees them? You are linking to a test file but if you have this in a build, and you specify the known helpers in webpack.config.js, and you write them in a dir (say src/helpers), and then you reference them in a hbs file with double brackets, I can't get them to work. I can get them to work as partials -- {{> nameOfHelper }}, but not as helpers -- {{ nameOfHelper }}. Personal project (exploratory) where this is not working:

https://github.com/davedub/handlepack

mAAdhaTTah commented 6 years ago

@davedub Best bet is to put it in an entry point or in a separate module imported by the entry point. Register them as early as possible so you don't accidentally attempt to run template functions before they've been registered.

davedub commented 6 years ago

@mAAdhaTTah Yep, was making it harder than it needed to be. Thanks for the tip. Adding the helper registers to the entry point of the app (in this case, app.js) and making sure the loader is fully configured in webpack.config.js, helpers work as indicated. @villeristi if you are still interested in an example, my project (linked above) has Handlebars helpers and partials pre-compiling via Webpack v2. I found the examples in the handlebars-loader project (which seem to be from Webpack v1) - while it's nice they are there - still hard to follow.

Vadorequest commented 6 years ago

would definitely be nice to have a proper solution.

impankratov commented 6 years ago

Managed to get this working. All you need to do is (just as @mAAdhaTTah said) to register helpers manually.

In short:

Example

victorgb6 commented 4 years ago

I've tried @impankratov solution for "handlebars-helpers" library but I cannot make it work, anyone has acomplished this and could share an example of the config?

Thanks!

vmohir commented 4 years ago

Thanks @impankratov. Here's an example based on your approach:

const Handlebars = require('handlebars/runtime');
Handlebars.registerHelper('loud', function(aString) {
  return aString.toUpperCase();
});
module.exports = Handlebars;
wehttam0 commented 3 years ago

@gvmohzibat requiring 'handlebars/runtime' instead of just 'handlebars' did the trick!