jonschlinkert / template

Render templates from any engine. Make custom template types, use layouts on pages, partials or any custom template type, custom delimiters, helpers, middleware, routes, loaders, and lots more. Powers Assemble v0.6.0, Verb v0.3.0 and your application.
https://github.com/jonschlinkert
MIT License
52 stars 7 forks source link

helper options #6

Closed jonschlinkert closed 9 years ago

jonschlinkert commented 9 years ago

I think we need to have an option or property somewhere dedicated to helper options.

Currently we're just winging it:

var extend = require('extend-shallow');

template.helper('foo', function (options) {
  var opts = extend({}, this.app.options, options);
  // do stuff
});

It's awesome how easy it is to pass options to helpers, but those options shouldn't be mixed in with the general/global options.

Of course, any helper author can namespace the helper's options however they see fit, but I'd really prefer to have a convention for doing it.

doowb commented 9 years ago

since we're building context for each page, we can do that while binding helpers also... so inside a helper they would be able to access it like...

var extend = require('extend-shallow');

template.helper('foo', function (options) {
  // this.options is only for the specific helper
  var opts = extend({}, this.options, options);
  // do stuff
});

Then when adding options to template for that helper:

template.option({
  foo: {
    bar: 'this is just for the foo helper';
  }
});

And in our bind logic, we only bind options for that helper:

var self = this;
var locals = self.context();
var helpers = self._.helpers;
locals.helpers = _.transform(helpers, function (acc, fn, key) {
    var o = {};
    o.context = locals;
    o.app = self;
    o.options = self.option(key) || {};
    acc[key] = _.bind(fn, o);
});

Just sudo code above, but I think that'll work and it'll match up the helper with the options by the name of the helper.

jonschlinkert commented 9 years ago

great idea. doing this.options has crossed my mind after I posted, but was still thinking it would be better to have a property on template.options, e.g

template.option({
  helperOpts: {}
});

But it didn't occur to me to match up the options like that. we could still implement this.options.helperOpts later if it's proven to be needed

doowb commented 9 years ago

All options are passed into helpers now as this.options. Can this be closed or should the code be updated to only pass in options that match the helper name?

akileez commented 9 years ago

Sorry to interject but just for my understanding ...by doing the following ...

exports.somehelper = function (body, options, locals) {
  // this.options are options for this particular helper ???
  options = extend(Array.prototype.pop.call(arguments), this.options,  locals);
...
}

only affects this particular helper if I define options for it? It does not mess with locals in anyway? doesn't seem like it but I just want to confirm. I use the hell out of locals in all my helpers. any significant alternation means I need to adjust ...

doowb commented 9 years ago

No, the options don't mess with any locals that you're passing into the helper.

akileez commented 9 years ago

thanks @doowb for the confirm.

jonschlinkert commented 9 years ago

closing since this is possible out-of-the-box