Permalink
Browse files

Add processAST option.

  • Loading branch information...
1 parent f6b88fb commit 589749930d6bf1e5febcada7660d842e16783d30 @jmorrell jmorrell committed Mar 7, 2013
Showing with 103 additions and 17 deletions.
  1. +15 −0 Gruntfile.js
  2. +19 −1 README.md
  3. +18 −0 docs/handlebars-options.md
  4. +24 −16 tasks/handlebars.js
  5. +17 −0 test/expected/process_ast.js
  6. +10 −0 test/handlebars_test.js
View
@@ -97,6 +97,21 @@ module.exports = function(grunt) {
'tmp/processcontent.js': ['test/fixtures/has-spaces.hbs']
}
},
+ process_ast: {
+ options: {
+ processAST: function(ast) {
+ ast.statements.forEach(function(statement, i) {
+ if (statement.type === 'partial') {
+ ast.statements[i] = { type: 'content', string: 'Fooville' };
+ }
+ });
+ return ast;
+ }
+ },
+ files: {
+ 'tmp/process_ast.js': ['test/fixtures/one.hbs']
+ }
+ },
amd_compile: {
options: {
amd: true
View
@@ -96,6 +96,24 @@ options: {
}
```
+#### processAST
+Type: `function`
+
+This option accepts a function which takes one argument (the parsed Abstract Syntax Tree) and returns a modified version which will be used as the source for the precompiled template object. The example below removes any partial and replaces it with the text `foo`.
+
+```js
+options: {
+ processAST: function(ast) {
+ ast.statements.forEach(function(statement, i) {
+ if (statement.type === 'partial') {
+ ast.statements[i] = { type: 'content', string: 'foo' };
+ }
+ });
+ return ast;
+ }
+}
+```
+
#### processName
Type: `function`
@@ -190,4 +208,4 @@ handlebars: {
Task submitted by [Tim Branyen](http://tbranyen.com)
-*This file was generated on Wed Feb 27 2013 09:38:15.*
+*This file was generated on Wed Mar 06 2013 23:56:18.*
View
@@ -67,6 +67,24 @@ options: {
}
```
+## processAST
+Type: `function`
+
+This option accepts a function which takes one argument (the parsed Abstract Syntax Tree) and returns a modified version which will be used as the source for the precompiled template object. The example below removes any partial and replaces it with the text `foo`.
+
+```js
+options: {
+ processAST: function(ast) {
+ ast.statements.forEach(function(statement, i) {
+ if (statement.type === 'partial') {
+ ast.statements[i] = { type: 'content', string: 'foo' };
+ }
+ });
+ return ast;
+ }
+}
+```
+
## processName
Type: `function`
View
@@ -15,17 +15,20 @@ module.exports = function(grunt) {
// content conversion for templates
var defaultProcessContent = function(content) { return content; };
+ // AST processing for templates
+ var defaultProcessAST = function(ast) { return ast; };
+
// filename conversion for templates
var defaultProcessName = function(name) { return name; };
// filename conversion for partials
var defaultProcessPartialName = function(filePath) {
var pieces = _.last(filePath.split('/')).split('.');
var name = _(pieces).without(_.last(pieces)).join('.'); // strips file extension
- if (name.charAt(0) === '_') {
- name = name.substr(1, name.length); // strips leading _ character
- }
- return name;
+ if (name.charAt(0) === '_') {
+ name = name.substr(1, name.length); // strips leading _ character
+ }
+ return name;
};
grunt.registerMultiTask('handlebars', 'Compile handlebars templates and partials.', function() {
@@ -38,12 +41,12 @@ module.exports = function(grunt) {
grunt.verbose.writeflags(options, 'Options');
var nsInfo;
- if (options.namespace !== false) {
+ if (options.namespace !== false) {
nsInfo = helpers.getNamespaceDeclaration(options.namespace);
}
-
- // assign regex for partials directory detection
- var partialsPathRegex = options.partialsPathRegex || /./;
+
+ // assign regex for partials directory detection
+ var partialsPathRegex = options.partialsPathRegex || /./;
// assign regex for partial detection
var isPartial = options.partialRegex || /^_/;
@@ -52,6 +55,7 @@ module.exports = function(grunt) {
var processContent = options.processContent || defaultProcessContent;
var processName = options.processName || defaultProcessName;
var processPartialName = options.processPartialName || defaultProcessPartialName;
+ var processAST = options.processAST || defaultProcessAST;
this.files.forEach(function(f) {
var partials = [];
@@ -69,9 +73,13 @@ module.exports = function(grunt) {
})
.forEach(function(filepath) {
var src = processContent(grunt.file.read(filepath));
- var compiled, filename;
+ var Handlebars = require('handlebars');
+ var ast, compiled, filename;
try {
- compiled = require('handlebars').precompile(src);
+ // parse the handlebars template into it's AST
+ ast = processAST(Handlebars.parse(src));
+ compiled = Handlebars.precompile(ast);
+
// if configured to, wrap template in Handlebars.template call
if (options.wrapped) {
compiled = 'Handlebars.template('+compiled+')';
@@ -87,13 +95,13 @@ module.exports = function(grunt) {
}
// register partial or add template to namespace
- if (partialsPathRegex.test(filepath) && isPartial.test(_.last(filepath.split('/')))) {
+ if (partialsPathRegex.test(filepath) && isPartial.test(_.last(filepath.split('/')))) {
filename = processPartialName(filepath);
- if (options.partialsUseNamespace === true) {
- partials.push('Handlebars.registerPartial('+JSON.stringify(filename)+', '+nsInfo.namespace+'['+JSON.stringify(filename)+'] = '+compiled+');');
- } else {
- partials.push('Handlebars.registerPartial('+JSON.stringify(filename)+', '+compiled+');');
- }
+ if (options.partialsUseNamespace === true) {
+ partials.push('Handlebars.registerPartial('+JSON.stringify(filename)+', '+nsInfo.namespace+'['+JSON.stringify(filename)+'] = '+compiled+');');
+ } else {
+ partials.push('Handlebars.registerPartial('+JSON.stringify(filename)+', '+compiled+');');
+ }
} else {
filename = processName(filepath);
if (options.namespace !== false) {
@@ -0,0 +1,17 @@
+this["JST"] = this["JST"] || {};
+
+this["JST"]["test/fixtures/one.hbs"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
+ this.compilerInfo = [2,'>= 1.0.0-rc.3'];
+helpers = helpers || Handlebars.helpers; data = data || {};
+ var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression;
+
+
+ buffer += "<p>Hello, my name is ";
+ if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ buffer += escapeExpression(stack1)
+ + ". I live in "
+ + "Fooville"
+ + "</p>";
+ return buffer;
+ });
View
@@ -81,6 +81,16 @@ exports.handlebars = {
test.done();
},
+ process_ast: function(test) {
+ 'use strict';
+ test.expect(1);
+
+ var actual = grunt.file.read('tmp/process_ast.js');
+ var expected = grunt.file.read('test/expected/process_ast.js');
+ test.equal(actual, expected, 'should allow the AST to be modified before compilation');
+
+ test.done();
+ },
amd_compile: function(test) {
'use strict';
test.expect(1);

0 comments on commit 5897499

Please sign in to comment.