gruntjs / grunt-contrib-handlebars

Precompile Handlebars templates to JST file.
http://gruntjs.com/
MIT License
282 stars 126 forks source link

Using commonjs:true generates incorrect JS code (0.10.2) #151

Open rally25rs opened 9 years ago

rally25rs commented 9 years ago

Using v0.10.2, if commonjs:true is set in options, then the output module JS file puts each template into a return statement, so the resulting file has multiple returns from the same function.

Gruntfile.js:

'use strict';

module.exports = function (grunt) {
  grunt.initConfig({
    handlebars: {
        compile: {
          files: [{
            dest: 'dist/templates.js',
            src: 'src/**/*.hbs'
          }],
          options: {
            commonjs: true,
            namespace: false
          }
        }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-handlebars');

  grunt.registerTask('default', ['handlebars:compile']);
};

The /src directory contains 2 files:

src/one.hbs

<h1>template one</h1>

src/two.hbs

<h2>template two</h2>

The resulting dist/templates.js is:

module.exports = function(Handlebars) {

return Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
    return "<h1>template one</h1>";
},"useData":true});

return Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
    return "<h2>template two</h2>";
},"useData":true});

};

Note that the generated function has 2 return statements, one for each template.

module.exports = function(Handlebars) {
    return Handlebars.template(...
    return Handlebars.template(...
}

This was discovered after an upgrade from v0.9.1 (which used Handlebars 2) to v0.10.2 (which uses Handlebars 3)

If I backdate grunt-contrib-handlebars to v0.9.1 then the generated dist/templates.js file is:

module.exports = function(Handlebars) {

var templates = {};

templates["src/one.hbs"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
  return "<h1>template one</h1>";
  },"useData":true});

templates["src/two.hbs"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
  return "<h2>template two</h2>";
  },"useData":true});

return templates;

};

which is the correct/expected output.

rally25rs commented 9 years ago

Workaround is to add a namespace option set to a string. Then the generated code is usable.

For example, with the option namespace:'templates' :

module.exports = function(Handlebars) {

this["templates"] = this["templates"] || {};

this["templates"]["src/one.hbs"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
    return "<h1>template one</h1>";
},"useData":true});

this["templates"]["src/two.hbs"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
    return "<h2>template two</h2>";
},"useData":true});

return this["templates"];

};
skanaar commented 8 years ago

We have stumbled on this pretty hard. While the workaround works it does not work as it says in the documentation.