From 373d402b5f93c6573529e464c413c10a5bae3f52 Mon Sep 17 00:00:00 2001 From: Larry Davis Date: Mon, 28 Jul 2014 10:23:47 -0700 Subject: [PATCH 1/3] Use nsdeclare for namespace declarations --- package.json | 3 +- tasks/handlebars.js | 48 +++++++++++++++----------- tasks/lib/handlebars.js | 18 ---------- test/expected/handlebarsnowrap.js | 4 +-- test/expected/namespace_as_function.js | 6 ++-- test/expected/partials_path_regex.js | 4 +-- 6 files changed, 36 insertions(+), 47 deletions(-) delete mode 100644 tasks/lib/handlebars.js diff --git a/package.json b/package.json index 5124409..2879bdc 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,9 @@ "test": "grunt test" }, "dependencies": { + "chalk": "~0.4.0", "handlebars": "~1.3.0", - "chalk": "~0.4.0" + "nsdeclare": "0.1.0" }, "devDependencies": { "grunt-contrib-jshint": "~0.6.0", diff --git a/tasks/handlebars.js b/tasks/handlebars.js index e986d1c..6f09ab0 100644 --- a/tasks/handlebars.js +++ b/tasks/handlebars.js @@ -8,10 +8,10 @@ 'use strict'; var chalk = require('chalk'); +var nsdeclare = require('nsdeclare'); module.exports = function(grunt) { var _ = grunt.util._; - var getNamespaceDeclaration = require('./lib/handlebars').getNamespaceDeclaration; // content conversion for templates var defaultProcessContent = function(content) { return content; }; @@ -23,8 +23,8 @@ module.exports = function(grunt) { var defaultProcessName = function(name) { return name; }; // filename conversion for partials - var defaultProcessPartialName = function(filePath) { - var pieces = _.last(filePath.split('/')).split('.'); + 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 @@ -56,15 +56,6 @@ module.exports = function(grunt) { var processAST = options.processAST || defaultProcessAST; var useNamespace = options.namespace !== false; - var namespaceInfo = _.memoize(function(filepath) { - if (!useNamespace) {return undefined;} - if (_.isFunction(options.namespace)) { - return getNamespaceDeclaration(options.namespace(filepath)); - } else { - return getNamespaceDeclaration(options.namespace); - } - }); - // assign compiler options var compilerOptions = options.compilerOptions || {}, filesCount = 0; @@ -72,9 +63,26 @@ module.exports = function(grunt) { this.files.forEach(function(f) { var partials = []; var templates = []; - var nsDeclarations = {}; + + // Namespace info for current template var nsInfo; + // Map of already declared namespace parts + var nsDeclarations = {}; + + // nsdeclare options when fetching namespace info + var nsDeclareOptions = { response: 'details', declared: nsDeclarations }; + + // Just get the namespace info for a given template + var getNamespaceInfo = _.memoize(function(filepath) { + if (!useNamespace) {return undefined;} + if (_.isFunction(options.namespace)) { + return nsdeclare(options.namespace(filepath), nsDeclareOptions); + } else { + return nsdeclare(options.namespace, nsDeclareOptions); + } + }); + // iterate files, processing partials and templates separately f.src.filter(function(filepath) { // Warn on and remove invalid source files (if nonull was set). @@ -87,11 +95,6 @@ module.exports = function(grunt) { }) .forEach(function(filepath) { var src = processContent(grunt.file.read(filepath), filepath); - nsInfo = namespaceInfo(filepath); - if (nsInfo) { - // save a map of declarations so we can put them at the top of the file later - nsDeclarations[nsInfo.namespace] = nsInfo.declaration; - } var Handlebars = require('handlebars'); var ast, compiled, filename; @@ -113,16 +116,22 @@ module.exports = function(grunt) { if (partialsPathRegex.test(filepath) && isPartial.test(_.last(filepath.split('/')))) { filename = processPartialName(filepath); if (options.partialsUseNamespace === true) { + nsInfo = getNamespaceInfo(filepath); + + partials.push(nsInfo.declaration); partials.push('Handlebars.registerPartial('+JSON.stringify(filename)+', '+nsInfo.namespace+'['+JSON.stringify(filename)+'] = '+compiled+');'); } else { partials.push('Handlebars.registerPartial('+JSON.stringify(filename)+', '+compiled+');'); } } else { + nsInfo = getNamespaceInfo(filepath); + if(options.amd && !useNamespace) { compiled = 'return ' + compiled; } filename = processName(filepath); if (useNamespace) { + templates.push(nsInfo.declaration); templates.push(nsInfo.namespace+'['+JSON.stringify(filename)+'] = '+compiled+';'); } else if (options.commonjs === true) { templates.push('templates['+JSON.stringify(filename)+'] = '+compiled+';'); @@ -137,9 +146,6 @@ module.exports = function(grunt) { grunt.log.warn('Destination not written because compiled files were empty.'); } else { if (useNamespace) { - var declarations = _.values(nsDeclarations).join(options.separator); - output.unshift(declarations); - if (options.node) { output.unshift('Handlebars = glob.Handlebars || require(\'handlebars\');'); output.unshift('var glob = (\'undefined\' === typeof window) ? global : window,'); diff --git a/tasks/lib/handlebars.js b/tasks/lib/handlebars.js deleted file mode 100644 index 8b6df2e..0000000 --- a/tasks/lib/handlebars.js +++ /dev/null @@ -1,18 +0,0 @@ -exports.getNamespaceDeclaration = function(ns) { - var output = []; - var curPath = 'this'; - if (ns !== 'this') { - var nsParts = ns.split('.'); - nsParts.forEach(function(curPart, index) { - if (curPart !== 'this') { - curPath += '[' + JSON.stringify(curPart) + ']'; - output.push(curPath + ' = ' + curPath + ' || {};'); - } - }); - } - - return { - namespace: curPath, - declaration: output.join('\n') - }; -}; diff --git a/test/expected/handlebarsnowrap.js b/test/expected/handlebarsnowrap.js index 0518c7f..3cb2758 100644 --- a/test/expected/handlebarsnowrap.js +++ b/test/expected/handlebarsnowrap.js @@ -1,5 +1,3 @@ -this["JST"] = this["JST"] || {}; - Handlebars.registerPartial("partial", function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; @@ -9,6 +7,8 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; return "Canada"; }); +this["JST"] = this["JST"] || {}; + this["JST"]["test/fixtures/one.hbs"] = function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); partials = this.merge(partials, Handlebars.partials); data = data || {}; diff --git a/test/expected/namespace_as_function.js b/test/expected/namespace_as_function.js index 084aa67..7f5218d 100644 --- a/test/expected/namespace_as_function.js +++ b/test/expected/namespace_as_function.js @@ -1,8 +1,5 @@ this["JST"] = this["JST"] || {}; this["JST"]["countries"] = this["JST"]["countries"] || {}; -this["JST"] = this["JST"] || {}; -this["JST"]["treeNav"] = this["JST"]["treeNav"] || {}; -this["JST"]["treeNav"]["leaves"] = this["JST"]["treeNav"]["leaves"] || {}; this["JST"]["countries"]["basic"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; @@ -13,6 +10,9 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; return "Basic template that does nothing."; }); +this["JST"]["treeNav"] = this["JST"]["treeNav"] || {}; +this["JST"]["treeNav"]["leaves"] = this["JST"]["treeNav"]["leaves"] || {}; + this["JST"]["treeNav"]["leaves"]["basic"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; diff --git a/test/expected/partials_path_regex.js b/test/expected/partials_path_regex.js index 498b08c..05fa44e 100644 --- a/test/expected/partials_path_regex.js +++ b/test/expected/partials_path_regex.js @@ -1,5 +1,3 @@ -this["JST"] = this["JST"] || {}; - Handlebars.registerPartial("partial", Handlebars.template(function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; @@ -9,6 +7,8 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; return "Canada"; })); +this["JST"] = this["JST"] || {}; + this["JST"]["test/fixtures/one.hbs"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); partials = this.merge(partials, Handlebars.partials); data = data || {}; From 35f627a98089f7e5e88b6901040f6e259bf9cd86 Mon Sep 17 00:00:00 2001 From: Larry Davis Date: Mon, 28 Jul 2014 10:25:35 -0700 Subject: [PATCH 2/3] Make naming consistent for cached regular expressions --- tasks/handlebars.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/handlebars.js b/tasks/handlebars.js index 6f09ab0..e3c72a1 100644 --- a/tasks/handlebars.js +++ b/tasks/handlebars.js @@ -47,7 +47,7 @@ module.exports = function(grunt) { var partialsPathRegex = options.partialsPathRegex || /./; // assign regex for partial detection - var isPartial = options.partialRegex || /^_/; + var isPartialRegex = options.partialRegex || /^_/; // assign transformation functions var processContent = options.processContent || defaultProcessContent; @@ -113,7 +113,7 @@ module.exports = function(grunt) { } // register partial or add template to namespace - if (partialsPathRegex.test(filepath) && isPartial.test(_.last(filepath.split('/')))) { + if (partialsPathRegex.test(filepath) && isPartialRegex.test(_.last(filepath.split('/')))) { filename = processPartialName(filepath); if (options.partialsUseNamespace === true) { nsInfo = getNamespaceInfo(filepath); From eee220b0258d27881c9f14fe2f9e4a10f4a0efdd Mon Sep 17 00:00:00 2001 From: Larry Davis Date: Mon, 28 Jul 2014 10:30:29 -0700 Subject: [PATCH 3/3] Put default values of options on a new line as intended --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 626b2c3..9aeb52a 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,14 @@ Task targets, files and options may be specified according to the grunt [Configu #### separator Type: `String` + Default: `linefeed + linefeed` Concatenated files will be joined on this string. #### namespace Type: `String` or `false` or `function` + Default: `'JST'` The namespace in which the precompiled templates will be assigned. *Use dot notation (e.g. App.Templates) for nested namespaces or false for no namespace wrapping.* When false with `amd` option set `true`, templates will be returned directly from the AMD wrapper. @@ -65,18 +67,21 @@ options: { #### partialsUseNamespace Type: `Boolean` + Default: `false` When set to `true`, partials will be registered in the `namespace` in addition to templates. #### wrapped Type: `Boolean` + Default: `true` Determine if preprocessed template functions will be wrapped in Handlebars.template function. #### node Type: `Boolean` + Default: `false` Enable the compiled file to be required on node.js by preppending and appending proper declarations. You can use the file safely on the front-end. @@ -85,6 +90,7 @@ For this option to work you need to define the `namespace` option. #### amd Type: `Boolean` or `String` or `Array` + Default: `false` Wraps the output file with an AMD define function and returns the compiled template namespace unless namespace has been explicitly set to false in which case the template function will be returned directly. @@ -102,6 +108,7 @@ define(['handlebars'], function(Handlebars) { #### commonjs Type: `Boolean` + Default: `false` Wraps the output file in a CommonJS module function, exporting the compiled templates. It will also add templates to the template namespace, unless `namespace` is explicitly set to `false`. @@ -185,6 +192,7 @@ Note: If processPartialName is not provided as an option the default assumes tha #### partialRegex Type: `Regexp` + Default: `/^_/` This option accepts a regex that defines the prefix character that is used to identify Handlebars partial files. @@ -198,6 +206,7 @@ options: { #### partialsPathRegex Type: `Regexp` + Default: `/./` This option accepts a regex that defines the path to a directory of Handlebars partials files. The example below shows how to mark every file in a specific directory as a partial. @@ -211,6 +220,7 @@ options: { #### compilerOptions Type `Object` + Default: `{}` This option allows you to specify a hash of options which will be passed directly to the Handlebars compiler.