328 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			328 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /* eslint-disable no-console */ | |||
|  | 'use strict'; | |||
|  | 
 | |||
|  | // istanbul ignore next
 | |||
|  | 
 | |||
|  | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } | |||
|  | 
 | |||
|  | // istanbul ignore next
 | |||
|  | 
 | |||
|  | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | |||
|  | 
 | |||
|  | var _neoAsync = require('neo-async'); | |||
|  | 
 | |||
|  | var _neoAsync2 = _interopRequireDefault(_neoAsync); | |||
|  | 
 | |||
|  | var _fs = require('fs'); | |||
|  | 
 | |||
|  | var _fs2 = _interopRequireDefault(_fs); | |||
|  | 
 | |||
|  | var _handlebars = require('./handlebars'); | |||
|  | 
 | |||
|  | var Handlebars = _interopRequireWildcard(_handlebars); | |||
|  | 
 | |||
|  | var _path = require('path'); | |||
|  | 
 | |||
|  | var _sourceMap = require('source-map'); | |||
|  | 
 | |||
|  | module.exports.loadTemplates = function (opts, callback) { | |||
|  |   loadStrings(opts, function (err, strings) { | |||
|  |     if (err) { | |||
|  |       callback(err); | |||
|  |     } else { | |||
|  |       loadFiles(opts, function (err, files) { | |||
|  |         if (err) { | |||
|  |           callback(err); | |||
|  |         } else { | |||
|  |           opts.templates = strings.concat(files); | |||
|  |           callback(undefined, opts); | |||
|  |         } | |||
|  |       }); | |||
|  |     } | |||
|  |   }); | |||
|  | }; | |||
|  | 
 | |||
|  | function loadStrings(opts, callback) { | |||
|  |   var strings = arrayCast(opts.string), | |||
|  |       names = arrayCast(opts.name); | |||
|  | 
 | |||
|  |   if (names.length !== strings.length && strings.length > 1) { | |||
|  |     return callback(new Handlebars.Exception('Number of names did not match the number of string inputs')); | |||
|  |   } | |||
|  | 
 | |||
|  |   _neoAsync2['default'].map(strings, function (string, callback) { | |||
|  |     if (string !== '-') { | |||
|  |       callback(undefined, string); | |||
|  |     } else { | |||
|  |       (function () { | |||
|  |         // Load from stdin
 | |||
|  |         var buffer = ''; | |||
|  |         process.stdin.setEncoding('utf8'); | |||
|  | 
 | |||
|  |         process.stdin.on('data', function (chunk) { | |||
|  |           buffer += chunk; | |||
|  |         }); | |||
|  |         process.stdin.on('end', function () { | |||
|  |           callback(undefined, buffer); | |||
|  |         }); | |||
|  |       })(); | |||
|  |     } | |||
|  |   }, function (err, strings) { | |||
|  |     strings = strings.map(function (string, index) { | |||
|  |       return { | |||
|  |         name: names[index], | |||
|  |         path: names[index], | |||
|  |         source: string | |||
|  |       }; | |||
|  |     }); | |||
|  |     callback(err, strings); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | function loadFiles(opts, callback) { | |||
|  |   // Build file extension pattern
 | |||
|  |   var extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-[\]]/g, function (arg) { | |||
|  |     return '\\' + arg; | |||
|  |   }); | |||
|  |   extension = new RegExp('\\.' + extension + '$'); | |||
|  | 
 | |||
|  |   var ret = [], | |||
|  |       queue = (opts.files || []).map(function (template) { | |||
|  |     return { template: template, root: opts.root }; | |||
|  |   }); | |||
|  |   _neoAsync2['default'].whilst(function () { | |||
|  |     return queue.length; | |||
|  |   }, function (callback) { | |||
|  |     var _queue$shift = queue.shift(); | |||
|  | 
 | |||
|  |     var path = _queue$shift.template; | |||
|  |     var root = _queue$shift.root; | |||
|  | 
 | |||
|  |     _fs2['default'].stat(path, function (err, stat) { | |||
|  |       if (err) { | |||
|  |         return callback(new Handlebars.Exception('Unable to open template file "' + path + '"')); | |||
|  |       } | |||
|  | 
 | |||
|  |       if (stat.isDirectory()) { | |||
|  |         opts.hasDirectory = true; | |||
|  | 
 | |||
|  |         _fs2['default'].readdir(path, function (err, children) { | |||
|  |           /* istanbul ignore next : Race condition that being too lazy to test */ | |||
|  |           if (err) { | |||
|  |             return callback(err); | |||
|  |           } | |||
|  |           children.forEach(function (file) { | |||
|  |             var childPath = path + '/' + file; | |||
|  | 
 | |||
|  |             if (extension.test(childPath) || _fs2['default'].statSync(childPath).isDirectory()) { | |||
|  |               queue.push({ template: childPath, root: root || path }); | |||
|  |             } | |||
|  |           }); | |||
|  | 
 | |||
|  |           callback(); | |||
|  |         }); | |||
|  |       } else { | |||
|  |         _fs2['default'].readFile(path, 'utf8', function (err, data) { | |||
|  |           /* istanbul ignore next : Race condition that being too lazy to test */ | |||
|  |           if (err) { | |||
|  |             return callback(err); | |||
|  |           } | |||
|  | 
 | |||
|  |           if (opts.bom && data.indexOf('') === 0) { | |||
|  |             data = data.substring(1); | |||
|  |           } | |||
|  | 
 | |||
|  |           // Clean the template name
 | |||
|  |           var name = path; | |||
|  |           if (!root) { | |||
|  |             name = _path.basename(name); | |||
|  |           } else if (name.indexOf(root) === 0) { | |||
|  |             name = name.substring(root.length + 1); | |||
|  |           } | |||
|  |           name = name.replace(extension, ''); | |||
|  | 
 | |||
|  |           ret.push({ | |||
|  |             path: path, | |||
|  |             name: name, | |||
|  |             source: data | |||
|  |           }); | |||
|  | 
 | |||
|  |           callback(); | |||
|  |         }); | |||
|  |       } | |||
|  |     }); | |||
|  |   }, function (err) { | |||
|  |     if (err) { | |||
|  |       callback(err); | |||
|  |     } else { | |||
|  |       callback(undefined, ret); | |||
|  |     } | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | module.exports.cli = function (opts) { | |||
|  |   if (opts.version) { | |||
|  |     console.log(Handlebars.VERSION); | |||
|  |     return; | |||
|  |   } | |||
|  | 
 | |||
|  |   if (!opts.templates.length && !opts.hasDirectory) { | |||
|  |     throw new Handlebars.Exception('Must define at least one template or directory.'); | |||
|  |   } | |||
|  | 
 | |||
|  |   if (opts.simple && opts.min) { | |||
|  |     throw new Handlebars.Exception('Unable to minimize simple output'); | |||
|  |   } | |||
|  | 
 | |||
|  |   var multiple = opts.templates.length !== 1 || opts.hasDirectory; | |||
|  |   if (opts.simple && multiple) { | |||
|  |     throw new Handlebars.Exception('Unable to output multiple templates in simple mode'); | |||
|  |   } | |||
|  | 
 | |||
|  |   // Force simple mode if we have only one template and it's unnamed.
 | |||
|  |   if (!opts.amd && !opts.commonjs && opts.templates.length === 1 && !opts.templates[0].name) { | |||
|  |     opts.simple = true; | |||
|  |   } | |||
|  | 
 | |||
|  |   // Convert the known list into a hash
 | |||
|  |   var known = {}; | |||
|  |   if (opts.known && !Array.isArray(opts.known)) { | |||
|  |     opts.known = [opts.known]; | |||
|  |   } | |||
|  |   if (opts.known) { | |||
|  |     for (var i = 0, len = opts.known.length; i < len; i++) { | |||
|  |       known[opts.known[i]] = true; | |||
|  |     } | |||
|  |   } | |||
|  | 
 | |||
|  |   var objectName = opts.partial ? 'Handlebars.partials' : 'templates'; | |||
|  | 
 | |||
|  |   var output = new _sourceMap.SourceNode(); | |||
|  |   if (!opts.simple) { | |||
|  |     if (opts.amd) { | |||
|  |       output.add('define([\'' + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n  Handlebars = Handlebars["default"];'); | |||
|  |     } else if (opts.commonjs) { | |||
|  |       output.add('var Handlebars = require("' + opts.commonjs + '");'); | |||
|  |     } else { | |||
|  |       output.add('(function() {\n'); | |||
|  |     } | |||
|  |     output.add('  var template = Handlebars.template, templates = '); | |||
|  |     if (opts.namespace) { | |||
|  |       output.add(opts.namespace); | |||
|  |       output.add(' = '); | |||
|  |       output.add(opts.namespace); | |||
|  |       output.add(' || '); | |||
|  |     } | |||
|  |     output.add('{};\n'); | |||
|  |   } | |||
|  | 
 | |||
|  |   opts.templates.forEach(function (template) { | |||
|  |     var options = { | |||
|  |       knownHelpers: known, | |||
|  |       knownHelpersOnly: opts.o | |||
|  |     }; | |||
|  | 
 | |||
|  |     if (opts.map) { | |||
|  |       options.srcName = template.path; | |||
|  |     } | |||
|  |     if (opts.data) { | |||
|  |       options.data = true; | |||
|  |     } | |||
|  | 
 | |||
|  |     var precompiled = Handlebars.precompile(template.source, options); | |||
|  | 
 | |||
|  |     // If we are generating a source map, we have to reconstruct the SourceNode object
 | |||
|  |     if (opts.map) { | |||
|  |       var consumer = new _sourceMap.SourceMapConsumer(precompiled.map); | |||
|  |       precompiled = _sourceMap.SourceNode.fromStringWithSourceMap(precompiled.code, consumer); | |||
|  |     } | |||
|  | 
 | |||
|  |     if (opts.simple) { | |||
|  |       output.add([precompiled, '\n']); | |||
|  |     } else { | |||
|  |       if (!template.name) { | |||
|  |         throw new Handlebars.Exception('Name missing for template'); | |||
|  |       } | |||
|  | 
 | |||
|  |       if (opts.amd && !multiple) { | |||
|  |         output.add('return '); | |||
|  |       } | |||
|  |       output.add([objectName, '[\'', template.name, '\'] = template(', precompiled, ');\n']); | |||
|  |     } | |||
|  |   }); | |||
|  | 
 | |||
|  |   // Output the content
 | |||
|  |   if (!opts.simple) { | |||
|  |     if (opts.amd) { | |||
|  |       if (multiple) { | |||
|  |         output.add(['return ', objectName, ';\n']); | |||
|  |       } | |||
|  |       output.add('});'); | |||
|  |     } else if (!opts.commonjs) { | |||
|  |       output.add('})();'); | |||
|  |     } | |||
|  |   } | |||
|  | 
 | |||
|  |   if (opts.map) { | |||
|  |     output.add('\n//# sourceMappingURL=' + opts.map + '\n'); | |||
|  |   } | |||
|  | 
 | |||
|  |   output = output.toStringWithSourceMap(); | |||
|  |   output.map = output.map + ''; | |||
|  | 
 | |||
|  |   if (opts.min) { | |||
|  |     output = minify(output, opts.map); | |||
|  |   } | |||
|  | 
 | |||
|  |   if (opts.map) { | |||
|  |     _fs2['default'].writeFileSync(opts.map, output.map, 'utf8'); | |||
|  |   } | |||
|  |   output = output.code; | |||
|  | 
 | |||
|  |   if (opts.output) { | |||
|  |     _fs2['default'].writeFileSync(opts.output, output, 'utf8'); | |||
|  |   } else { | |||
|  |     console.log(output); | |||
|  |   } | |||
|  | }; | |||
|  | 
 | |||
|  | function arrayCast(value) { | |||
|  |   value = value != null ? value : []; | |||
|  |   if (!Array.isArray(value)) { | |||
|  |     value = [value]; | |||
|  |   } | |||
|  |   return value; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * Run uglify to minify the compiled template, if uglify exists in the dependencies. | |||
|  |  * | |||
|  |  * We are using `require` instead of `import` here, because es6-modules do not allow | |||
|  |  * dynamic imports and uglify-js is an optional dependency. Since we are inside NodeJS here, this | |||
|  |  * should not be a problem. | |||
|  |  * | |||
|  |  * @param {string} output the compiled template | |||
|  |  * @param {string} sourceMapFile the file to write the source map to. | |||
|  |  */ | |||
|  | function minify(output, sourceMapFile) { | |||
|  |   try { | |||
|  |     // Try to resolve uglify-js in order to see if it does exist
 | |||
|  |     require.resolve('uglify-js'); | |||
|  |   } catch (e) { | |||
|  |     if (e.code !== 'MODULE_NOT_FOUND') { | |||
|  |       // Something else seems to be wrong
 | |||
|  |       throw e; | |||
|  |     } | |||
|  |     // it does not exist!
 | |||
|  |     console.error('Code minimization is disabled due to missing uglify-js dependency'); | |||
|  |     return output; | |||
|  |   } | |||
|  |   return require('uglify-js').minify(output.code, { | |||
|  |     sourceMap: { | |||
|  |       content: output.map, | |||
|  |       url: sourceMapFile | |||
|  |     } | |||
|  |   }); | |||
|  | } | |||
|  | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL2xpYi9wcmVjb21waWxlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozt3QkFDa0IsV0FBVzs7OztrQkFDZCxJQUFJOzs7OzBCQUNTLGNBQWM7O0lBQTlCLFVBQVU7O29CQUNDLE1BQU07O3lCQUNlLFlBQVk7O0FBR3hELE1BQU0sQ0FBQyxPQUFPLENBQUMsYUFBYSxHQUFHLFVBQVMsSUFBSSxFQUFFLFFBQVEsRUFBRTtBQUN0RCxhQUFXLENBQUMsSUFBSSxFQUFFLFVBQVMsR0FBRyxFQUFFLE9BQU8sRUFBRTtBQUN2QyxRQUFJLEdBQUcsRUFBRTtBQUNQLGNBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUNmLE1BQU07QUFDTCxlQUFTLENBQUMsSUFBSSxFQUFFLFVBQVMsR0FBRyxFQUFFLEtBQUssRUFBRTtBQUNuQyxZQUFJLEdBQUcsRUFBRTtBQUNQLGtCQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDZixNQUFNO0FBQ0wsY0FBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3ZDLGtCQUFRLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQzNCO09BQ0YsQ0FBQyxDQUFDO0tBQ0o7R0FDRixDQUFDLENBQUM7Q0FDSixDQUFDOztBQUVGLFNBQVMsV0FBVyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUU7QUFDbkMsTUFBSSxPQUFPLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7TUFDaEMsS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7O0FBRWpDLE1BQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxJQUM1QixPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtBQUN6QixXQUFPLFFBQVEsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsMkRBQTJELENBQUMsQ0FBQyxDQUFDO0dBQ3hH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
 |