-
Notifications
You must be signed in to change notification settings - Fork 250
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
issue/1802: inlined fix for duplicate handlebars namespaces (#1803)
- v5.42.7
- v5.42.6
- v5.42.5
- v5.42.4
- v5.42.3
- v5.42.2
- v5.42.1
- v5.42.0
- v5.41.14
- v5.41.13
- v5.41.12
- v5.41.11
- v5.41.10
- v5.41.9
- v5.41.8
- v5.41.7
- v5.41.6
- v5.41.5
- v5.41.4
- v5.41.3
- v5.41.2
- v5.41.1
- v5.41.0
- v5.40.15
- v5.40.14
- v5.40.13
- v5.40.12
- v5.40.11
- v5.40.10
- v5.40.9
- v5.40.8
- v5.40.7
- v5.40.6
- v5.40.5
- v5.40.4
- v5.40.3
- v5.40.2
- v5.40.1
- v5.40.0
- v5.39.15
- v5.39.14
- v5.39.13
- v5.39.12
- v5.39.11
- v5.39.10
- v5.39.9
- v5.39.8
- v5.39.7
- v5.39.6
- v5.39.5
- v5.39.4
- v5.39.3
- v5.39.2
- v5.39.1
- v5.39.0
- v5.38.2
- v5.38.1
- v5.38.0
- v5.37.9
- v5.37.8
- v5.37.7
- v5.37.6
- v5.37.5
- v5.37.4
- v5.37.3
- v5.37.2
- v5.37.1
- v5.37.0
- v5.36.3
- v5.36.2
- v5.36.1
- v5.36.0
- v5.35.7
- v5.35.6
- v5.35.5
- v5.35.4
- v5.35.3
- v5.35.2
- v5.35.1
- v5.35.0
- v5.34.1
- v5.34.0
- v5.33.13
- v5.33.12
- v5.33.11
- v5.33.10
- v5.33.9
- v5.33.8
- v5.33.7
- v5.33.6
- v5.33.5
- v5.33.4
- v5.33.3
- v5.33.2
- v5.33.1
- v5.33.0
- v5.32.6
- v5.32.5
- v5.32.4
- v5.32.3
- v5.32.2
- v5.32.1
- v5.32.0
- v5.31.31
- v5.31.30
- v5.31.29
- v5.31.28
- v5.31.27
- v5.31.26
- v5.31.25
- v5.31.24
- v5.31.23
- v5.31.22
- v5.31.21
- v5.31.20
- v5.31.19
- v5.31.18
- v5.31.17
- v5.31.16
- v5.31.15
- v5.31.14
- v5.31.13
- v5.31.12
- v5.31.11
- v5.31.10
- v5.31.9
- v5.31.8
- v5.31.7
- v5.31.6
- v5.31.5
- v5.31.4
- v5.31.3
- v5.31.2
- v5.31.1
- v5.31.0
- v5.30.4
- v5.30.3
- v5.30.2
- v5.30.1
- v5.30.0
- v5.29.4
- v5.29.3
- v5.29.2
- v5.29.1
- v5.29.0
- v5.28.15
- v5.28.14
- v5.28.13
- v5.28.12
- v5.28.11
- v5.28.10
- v5.28.9
- v5.28.8
- v5.28.7
- v5.28.6
- v5.28.5
- v5.28.4
- v5.28.3
- v5.28.2
- v5.28.1
- v5.28.0
- v5.27.0
- v5.26.1
- v5.26.0
- v5.25.2
- v5.25.1
- v5.25.0
- v5.24.8
- v5.24.7
- v5.24.6
- v5.24.5
- v5.24.4
- v5.24.3
- v5.24.2
- v5.24.1
- v5.24.0
- v5.23.0
- v5.22.11
- v5.22.10
- v5.22.9
- v5.22.8
- v5.22.7
- v5.22.6
- v5.22.5
- v5.22.4
- v5.22.3
- v5.22.2
- v5.22.1
- v5.22.0
- v5.21.0
- v5.20.2
- v5.20.1
- v5.20.0
- v5.19.6
- v5.19.5
- v5.19.4
- v5.19.3
- v5.19.2
- v5.19.1
- v5.19.0
- v5.18.8
- v5.18.7
- v5.18.6
- v5.18.5
- v5.18.4
- v5.18.3
- v5.18.2
- v5.18.1
- v5.18.0
- v5.17.7
- v5.17.6
- v5.17.5
- v5.17.4
- v5.17.3
- v5.17.2
- v5.17.1
- v5.17.0
- v5.16.0
- v5.15.5
- v5.15.4
- v5.15.3
- v5.15.2
- v5.15.1
- v5.15.0
- v5.14.0
- v5.13.0
- v5.12.2
- v5.12.1
- v5.12.0
- v5.11.0
- v5.10.1
- v5.10.0
- v5.9.0
- v5.8.1
- v5.8.0
- v5.7.1
- v5.7.0
- v5.6.1
- v5.6.0
- v5.5.1
- v5.5.0
- v5.4.0
- v5.3.0
- v5.2.0
- v5.1.0
- v5.0.0
- v4.5.0
- v4.4.2
- v4.4.1
- v4.4.0
- v4.3.0
- v4.2.0
- v4.1.1
- v4.1.0
- v4.0.1
- v4.0.0
- v3.5.8
- v3.5.7
- v3.5.6
- v3.5.5
- v3.5.4
- v3.5.3
- v3.5.2
- v3.5.1
- v3.5.0
- v3.4.0
- v3.3.0
- v3.2.2
- v3.2.1
- v3.2.0
- v3.1.0
- v3.0.0
1 parent
ccf3ca1
commit bd693dd
Showing
2 changed files
with
241 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
/* | ||
* grunt-contrib-handlebars | ||
* http://gruntjs.com/ | ||
* | ||
* Copyright (c) 2016 Tim Branyen, contributors | ||
* Licensed under the MIT license. | ||
*/ | ||
|
||
'use strict'; | ||
var chalk = require('chalk'); | ||
var nsdeclare = require('nsdeclare'); | ||
|
||
module.exports = function(grunt) { | ||
var _ = grunt.util._; | ||
|
||
// 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; | ||
}; | ||
|
||
var extractGlobalNamespace = function(nsDeclarations) { | ||
// Extract global namespace from any existing namespace declaration. | ||
// The purpose of this method is too fix an issue with AMD when using namespace as a function where the | ||
// nsInfo.namespace will contains the last namespace, not the global namespace. | ||
|
||
var declarations = _.keys(nsDeclarations); | ||
|
||
// no declaration found | ||
if (!declarations.length) { | ||
return ''; | ||
} | ||
|
||
// In case only one namespace has been declared it will only return it. | ||
if (declarations.length === 1) { | ||
return declarations[0]; | ||
} | ||
// We only need to take any declaration to extract the global namespace. | ||
// Another option might be find the shortest declaration which is the global one. | ||
var matches = declarations[0].match(/(this\[[^\[]+\])/g); | ||
return matches[0]; | ||
}; | ||
|
||
grunt.registerMultiTask('handlebars', 'Compile handlebars templates and partials.', function() { | ||
var options = this.options({ | ||
namespace: 'JST', | ||
separator: grunt.util.linefeed + grunt.util.linefeed, | ||
wrapped: true, | ||
amd: false, | ||
commonjs: false, | ||
knownHelpers: [], | ||
knownHelpersOnly: false | ||
}); | ||
|
||
// assign regex for partials directory detection | ||
var partialsPathRegex = options.partialsPathRegex || /./; | ||
|
||
// assign regex for partial detection | ||
var isPartialRegex = options.partialRegex || /^_/; | ||
|
||
// assign transformation functions | ||
var processContent = options.processContent || defaultProcessContent; | ||
var processName = options.processName || defaultProcessName; | ||
var processPartialName = options.processPartialName || defaultProcessPartialName; | ||
var processAST = options.processAST || defaultProcessAST; | ||
var useNamespace = options.namespace !== false; | ||
|
||
// assign compiler options | ||
var compilerOptions = options.compilerOptions || {}; | ||
var filesCount = 0; | ||
|
||
this.files.forEach(function(f) { | ||
var declarations = []; | ||
var partials = {}; | ||
var templates = {}; | ||
// template identifying parts | ||
var ast, compiled, filename; | ||
|
||
// 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); | ||
} | ||
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). | ||
if (!grunt.file.exists(filepath)) { | ||
grunt.log.warn('Source file "' + filepath + '" not found.'); | ||
return false; | ||
} | ||
return true; | ||
}) | ||
.forEach(function(filepath) { | ||
var src = processContent(grunt.file.read(filepath), filepath); | ||
|
||
var Handlebars = require('handlebars'); | ||
try { | ||
// parse the handlebars template into it's AST | ||
ast = processAST(Handlebars.parse(src)); | ||
compiled = Handlebars.precompile(ast, compilerOptions); | ||
|
||
// if configured to, wrap template in Handlebars.template call | ||
if (options.wrapped === true) { | ||
compiled = 'Handlebars.template(' + compiled + ')'; | ||
} | ||
} catch (e) { | ||
grunt.log.error(e); | ||
grunt.fail.warn('Handlebars failed to compile ' + filepath + '.'); | ||
} | ||
|
||
// register partial or add template to namespace | ||
if (partialsPathRegex.test(filepath) && isPartialRegex.test(_.last(filepath.split('/')))) { | ||
filename = processPartialName(filepath); | ||
if (options.partialsUseNamespace === true) { | ||
nsInfo = getNamespaceInfo(filepath); | ||
if (nsInfo.declaration) { | ||
declarations.push(nsInfo.declaration); | ||
} | ||
partials[nsInfo.namespace + ':' + JSON.stringify(filename)] = ('Handlebars.registerPartial(' + | ||
JSON.stringify(filename) + ', ' + nsInfo.namespace + '[' + JSON.stringify(filename) + '] = ' + | ||
compiled + ');'); | ||
} else { | ||
partials[JSON.stringify(filename)] = ('Handlebars.registerPartial(' + JSON.stringify(filename) + | ||
', ' + compiled + ');'); | ||
} | ||
} else { | ||
if ((options.amd || options.commonjs) && !useNamespace) { | ||
compiled = 'return ' + compiled; | ||
} | ||
filename = processName(filepath); | ||
if (useNamespace) { | ||
nsInfo = getNamespaceInfo(filepath); | ||
if (nsInfo.declaration) { | ||
declarations.push(nsInfo.declaration); | ||
} | ||
templates[nsInfo.namespace + ':' + JSON.stringify(filename)] = (nsInfo.namespace + '[' + | ||
JSON.stringify(filename) + '] = ' + compiled + ';'); | ||
} else if (options.commonjs === true) { | ||
templates[JSON.stringify(filename)] = compiled + ';'; | ||
} else { | ||
templates[JSON.stringify(filename)] = compiled; | ||
} | ||
} | ||
}); | ||
|
||
var output = declarations.concat(_.values(partials), _.values(templates)); | ||
if (output.length < 1) { | ||
grunt.log.warn('Destination not written because compiled files were empty.'); | ||
} else { | ||
if (useNamespace) { | ||
if (options.node) { | ||
output.unshift('Handlebars = glob.Handlebars || require(\'handlebars\');'); | ||
output.unshift('var glob = (\'undefined\' === typeof window) ? global : window,'); | ||
|
||
var nodeExport = 'if (typeof exports === \'object\' && exports) {'; | ||
nodeExport += 'module.exports = ' + nsInfo.namespace + ';}'; | ||
|
||
output.push(nodeExport); | ||
} | ||
|
||
} | ||
|
||
if (options.amd) { | ||
// Wrap the file in an AMD define fn. | ||
if (typeof options.amd === 'boolean') { | ||
output.unshift('define([\'handlebars\'], function(Handlebars) {'); | ||
} else if (typeof options.amd === 'string') { | ||
output.unshift('define([\'' + options.amd + '\'], function(Handlebars) {'); | ||
} else if (typeof options.amd === 'function') { | ||
output.unshift('define([\'' + options.amd(filename, ast, compiled) + '\'], function(Handlebars) {'); | ||
} else if (Array.isArray(options.amd)) { | ||
// convert options.amd to a string of dependencies for require([...]) | ||
var amdString = ''; | ||
for (var i = 0; i < options.amd.length; i++) { | ||
if (i !== 0) { | ||
amdString += ', '; | ||
} | ||
|
||
amdString += '\'' + options.amd[i] + '\''; | ||
} | ||
|
||
// Wrap the file in an AMD define fn. | ||
output.unshift('define([' + amdString + '], function(Handlebars) {'); | ||
} | ||
|
||
if (useNamespace) { | ||
// Namespace has not been explicitly set to false; the AMD | ||
// wrapper will return the object containing the template. | ||
output.push('return ' + extractGlobalNamespace(nsDeclarations) + ';'); | ||
} | ||
output.push('});'); | ||
} | ||
|
||
if (options.commonjs) { | ||
if (useNamespace) { | ||
output.push('return ' + nsInfo.namespace + ';'); | ||
} | ||
// Export the templates object for CommonJS environments. | ||
output.unshift('module.exports = function(Handlebars) {'); | ||
output.push('};'); | ||
} | ||
|
||
filesCount++; | ||
grunt.file.write(f.dest, output.join(grunt.util.normalizelf(options.separator))); | ||
grunt.verbose.writeln('File ' + chalk.cyan(f.dest) + ' created.'); | ||
} | ||
}); | ||
|
||
grunt.log.ok(filesCount + ' ' + grunt.util.pluralize(filesCount, 'file/files') + ' created.'); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters