diff options
author | kpdecker <kpdecker@gmail.com> | 2015-08-04 10:55:51 -0500 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2015-08-04 10:55:51 -0500 |
commit | 00f74420f949a42bedd99af022c20cdc5027228d (patch) | |
tree | 633639cb0fc33b0ac7cafed8d5a572c9afab21c3 | |
parent | a62cbad95acdf544dc9daae9834588453ee1f835 (diff) | |
download | handlebars.js-00f74420f949a42bedd99af022c20cdc5027228d.zip handlebars.js-00f74420f949a42bedd99af022c20cdc5027228d.tar.gz handlebars.js-00f74420f949a42bedd99af022c20cdc5027228d.tar.bz2 |
Convert precompiler template loading to async
-rwxr-xr-x | bin/handlebars | 18 | ||||
-rw-r--r-- | lib/precompiler.js | 105 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | spec/precompiler.js | 64 |
4 files changed, 113 insertions, 75 deletions
diff --git a/bin/handlebars b/bin/handlebars index 10cc6c5..bfe6680 100755 --- a/bin/handlebars +++ b/bin/handlebars @@ -100,14 +100,18 @@ var optimist = require('optimist') var argv = optimist.argv; -argv.templates = argv._; +argv.files = argv._; delete argv._; var Precompiler = require('../dist/cjs/precompiler'); -Precompiler.loadTemplates(argv); +Precompiler.loadTemplates(argv, function(err, opts) { + if (err) { + throw err; + } -if (argv.help || (!argv.templates.length && !argv.version)) { - optimist.showHelp(); -} else { - Precompiler.cli(argv); -} + if (opts.help || (!opts.templates.length && !opts.version)) { + optimist.showHelp(); + } else { + Precompiler.cli(opts); + } +}); diff --git a/lib/precompiler.js b/lib/precompiler.js index 2809b1b..8a2019d 100644 --- a/lib/precompiler.js +++ b/lib/precompiler.js @@ -1,62 +1,85 @@ /*eslint-disable no-console */ +import Async from 'async'; import fs from 'fs'; import * as Handlebars from './handlebars'; import {basename} from 'path'; import {SourceMapConsumer, SourceNode} from 'source-map'; import uglify from 'uglify-js'; -module.exports.loadTemplates = function(opts) { +module.exports.loadTemplates = function(opts, callback) { // Build file extension pattern let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; }); extension = new RegExp('\\.' + extension + '$'); - let ret = []; - function processTemplate(template, root) { - let path = template, - stat; - try { - stat = fs.statSync(template); - } catch (err) { - throw new Handlebars.Exception(`Unable to open template file "${template}"`); - } - - if (stat.isDirectory()) { - opts.hasDirectory = true; - - fs.readdirSync(template).map(function(file) { - let childPath = template + '/' + file; - - if (extension.test(childPath) || fs.statSync(childPath).isDirectory()) { - processTemplate(childPath, root || template); - } - }); - } else { - let data = fs.readFileSync(path, 'utf8'); + let ret = [], + queue = opts.files.map((template) => ({template, root: opts.root})); + Async.whilst(() => queue.length, function(callback) { + let {template: path, root} = queue.shift(); - if (opts.bom && data.indexOf('\uFEFF') === 0) { - data = data.substring(1); + fs.stat(path, function(err, stat) { + if (err) { + return callback(new Handlebars.Exception(`Unable to open template file "${path}"`)); } - // Clean the template name - if (!root) { - template = basename(template); - } else if (template.indexOf(root) === 0) { - template = template.substring(root.length + 1); + if (stat.isDirectory()) { + opts.hasDirectory = true; + + fs.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) { + let childPath = path + '/' + file; + + if (extension.test(childPath) || fs.statSync(childPath).isDirectory()) { + queue.push({template: childPath, root: root || path}); + } + }); + + callback(); + }); + } else { + fs.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('\uFEFF') === 0) { + data = data.substring(1); + } + + // Clean the template name + let name = path; + if (!root) { + name = 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(); + }); } - template = template.replace(extension, ''); + }); + }, + function(err) { + if (err) { + callback(err); + } else { + opts.templates = ret; - ret.push({ - path: path, - name: template, - source: data - }); + callback(undefined, opts); } - } - opts.templates.forEach(function(template) { - processTemplate(template, opts.root); }); - opts.templates = ret; -}; +} module.exports.cli = function(opts) { if (opts.version) { diff --git a/package.json b/package.json index 83f428d..b1cafee 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "node": ">=0.4.7" }, "dependencies": { + "async": "^1.4.0", "optimist": "^0.6.1", "source-map": "^0.1.40" }, diff --git a/spec/precompiler.js b/spec/precompiler.js index f9cc8fd..72a7ce6 100644 --- a/spec/precompiler.js +++ b/spec/precompiler.js @@ -153,38 +153,48 @@ describe('precompiler', function() { }); describe('#loadTemplates', function() { - it('should throw on missing template', function() { - shouldThrow(function() { - Precompiler.loadTemplates({templates: ['foo']}); - }, Handlebars.Exception, 'Unable to open template file "foo"'); + it('should throw on missing template', function(done) { + Precompiler.loadTemplates({files: ['foo']}, function(err) { + equal(err.message, 'Unable to open template file "foo"'); + done(); + }); }); - it('should enumerate directories by extension', function() { - var opts = {templates: [__dirname + '/artifacts'], extension: 'hbs'}; - Precompiler.loadTemplates(opts); - equal(opts.templates.length, 1); - equal(opts.templates[0].name, 'example_2'); - - opts = {templates: [__dirname + '/artifacts'], extension: 'handlebars'}; - Precompiler.loadTemplates(opts); - equal(opts.templates.length, 3); - equal(opts.templates[0].name, 'bom'); - equal(opts.templates[1].name, 'empty'); - equal(opts.templates[2].name, 'example_1'); + it('should enumerate directories by extension', function(done) { + Precompiler.loadTemplates({files: [__dirname + '/artifacts'], extension: 'hbs'}, function(err, opts) { + equal(opts.templates.length, 1); + equal(opts.templates[0].name, 'example_2'); + done(err); + }); }); - it('should handle regular expression characters in extensions', function() { - Precompiler.loadTemplates({templates: [__dirname + '/artifacts'], extension: 'hb(s'}); - // Success is not throwing + it('should enumerate all templates by extension', function(done) { + Precompiler.loadTemplates({files: [__dirname + '/artifacts'], extension: 'handlebars'}, function(err, opts) { + equal(opts.templates.length, 3); + equal(opts.templates[0].name, 'bom'); + equal(opts.templates[1].name, 'empty'); + equal(opts.templates[2].name, 'example_1'); + done(err); + }); }); - it('should handle BOM', function() { - var opts = {templates: [__dirname + '/artifacts/bom.handlebars'], extension: 'handlebars', bom: true}; - Precompiler.loadTemplates(opts); - equal(opts.templates[0].source, 'a'); + it('should handle regular expression characters in extensions', function(done) { + Precompiler.loadTemplates({files: [__dirname + '/artifacts'], extension: 'hb(s'}, function(err) { + // Success is not throwing + done(err); + }); + }); + it('should handle BOM', function(done) { + var opts = {files: [__dirname + '/artifacts/bom.handlebars'], extension: 'handlebars', bom: true}; + Precompiler.loadTemplates(opts, function(err, opts) { + equal(opts.templates[0].source, 'a'); + done(err); + }); }); - it('should handle different root', function() { - var opts = {templates: [__dirname + '/artifacts/empty.handlebars'], simple: true, root: 'foo/'}; - Precompiler.loadTemplates(opts); - equal(opts.templates[0].name, __dirname + '/artifacts/empty'); + it('should handle different root', function(done) { + var opts = {files: [__dirname + '/artifacts/empty.handlebars'], simple: true, root: 'foo/'}; + Precompiler.loadTemplates(opts, function(err, opts) { + equal(opts.templates[0].name, __dirname + '/artifacts/empty'); + done(err); + }); }); }); }); |