Convert precompiler template loading to async
This commit is contained in:
+11
-7
@@ -100,14 +100,18 @@ var optimist = require('optimist')
|
|||||||
|
|
||||||
|
|
||||||
var argv = optimist.argv;
|
var argv = optimist.argv;
|
||||||
argv.templates = argv._;
|
argv.files = argv._;
|
||||||
delete argv._;
|
delete argv._;
|
||||||
|
|
||||||
var Precompiler = require('../dist/cjs/precompiler');
|
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)) {
|
if (opts.help || (!opts.templates.length && !opts.version)) {
|
||||||
optimist.showHelp();
|
optimist.showHelp();
|
||||||
} else {
|
} else {
|
||||||
Precompiler.cli(argv);
|
Precompiler.cli(opts);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|||||||
+64
-41
@@ -1,62 +1,85 @@
|
|||||||
/*eslint-disable no-console */
|
/*eslint-disable no-console */
|
||||||
|
import Async from 'async';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as Handlebars from './handlebars';
|
import * as Handlebars from './handlebars';
|
||||||
import {basename} from 'path';
|
import {basename} from 'path';
|
||||||
import {SourceMapConsumer, SourceNode} from 'source-map';
|
import {SourceMapConsumer, SourceNode} from 'source-map';
|
||||||
import uglify from 'uglify-js';
|
import uglify from 'uglify-js';
|
||||||
|
|
||||||
module.exports.loadTemplates = function(opts) {
|
module.exports.loadTemplates = function(opts, callback) {
|
||||||
// Build file extension pattern
|
// Build file extension pattern
|
||||||
let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; });
|
let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; });
|
||||||
extension = new RegExp('\\.' + extension + '$');
|
extension = new RegExp('\\.' + extension + '$');
|
||||||
|
|
||||||
let ret = [];
|
let ret = [],
|
||||||
function processTemplate(template, root) {
|
queue = opts.files.map((template) => ({template, root: opts.root}));
|
||||||
let path = template,
|
Async.whilst(() => queue.length, function(callback) {
|
||||||
stat;
|
let {template: path, root} = queue.shift();
|
||||||
try {
|
|
||||||
stat = fs.statSync(template);
|
|
||||||
} catch (err) {
|
|
||||||
throw new Handlebars.Exception(`Unable to open template file "${template}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat.isDirectory()) {
|
fs.stat(path, function(err, stat) {
|
||||||
opts.hasDirectory = true;
|
if (err) {
|
||||||
|
return callback(new Handlebars.Exception(`Unable to open template file "${path}"`));
|
||||||
|
}
|
||||||
|
|
||||||
fs.readdirSync(template).map(function(file) {
|
if (stat.isDirectory()) {
|
||||||
let childPath = template + '/' + file;
|
opts.hasDirectory = true;
|
||||||
|
|
||||||
if (extension.test(childPath) || fs.statSync(childPath).isDirectory()) {
|
fs.readdir(path, function(err, children) {
|
||||||
processTemplate(childPath, root || template);
|
/* 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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
} else {
|
} else {
|
||||||
let data = fs.readFileSync(path, 'utf8');
|
opts.templates = ret;
|
||||||
|
|
||||||
if (opts.bom && data.indexOf('\uFEFF') === 0) {
|
callback(undefined, opts);
|
||||||
data = data.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean the template name
|
|
||||||
if (!root) {
|
|
||||||
template = basename(template);
|
|
||||||
} else if (template.indexOf(root) === 0) {
|
|
||||||
template = template.substring(root.length + 1);
|
|
||||||
}
|
|
||||||
template = template.replace(extension, '');
|
|
||||||
|
|
||||||
ret.push({
|
|
||||||
path: path,
|
|
||||||
name: template,
|
|
||||||
source: data
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
opts.templates.forEach(function(template) {
|
|
||||||
processTemplate(template, opts.root);
|
|
||||||
});
|
});
|
||||||
opts.templates = ret;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.cli = function(opts) {
|
module.exports.cli = function(opts) {
|
||||||
if (opts.version) {
|
if (opts.version) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"node": ">=0.4.7"
|
"node": ">=0.4.7"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"async": "^1.4.0",
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"source-map": "^0.1.40"
|
"source-map": "^0.1.40"
|
||||||
},
|
},
|
||||||
|
|||||||
+37
-27
@@ -153,38 +153,48 @@ describe('precompiler', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('#loadTemplates', function() {
|
describe('#loadTemplates', function() {
|
||||||
it('should throw on missing template', function() {
|
it('should throw on missing template', function(done) {
|
||||||
shouldThrow(function() {
|
Precompiler.loadTemplates({files: ['foo']}, function(err) {
|
||||||
Precompiler.loadTemplates({templates: ['foo']});
|
equal(err.message, 'Unable to open template file "foo"');
|
||||||
}, Handlebars.Exception, 'Unable to open template file "foo"');
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
it('should enumerate directories by extension', function() {
|
it('should enumerate directories by extension', function(done) {
|
||||||
var opts = {templates: [__dirname + '/artifacts'], extension: 'hbs'};
|
Precompiler.loadTemplates({files: [__dirname + '/artifacts'], extension: 'hbs'}, function(err, opts) {
|
||||||
Precompiler.loadTemplates(opts);
|
equal(opts.templates.length, 1);
|
||||||
equal(opts.templates.length, 1);
|
equal(opts.templates[0].name, 'example_2');
|
||||||
equal(opts.templates[0].name, 'example_2');
|
done(err);
|
||||||
|
});
|
||||||
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 handle regular expression characters in extensions', function() {
|
it('should enumerate all templates by extension', function(done) {
|
||||||
Precompiler.loadTemplates({templates: [__dirname + '/artifacts'], extension: 'hb(s'});
|
Precompiler.loadTemplates({files: [__dirname + '/artifacts'], extension: 'handlebars'}, function(err, opts) {
|
||||||
// Success is not throwing
|
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() {
|
it('should handle regular expression characters in extensions', function(done) {
|
||||||
var opts = {templates: [__dirname + '/artifacts/bom.handlebars'], extension: 'handlebars', bom: true};
|
Precompiler.loadTemplates({files: [__dirname + '/artifacts'], extension: 'hb(s'}, function(err) {
|
||||||
Precompiler.loadTemplates(opts);
|
// Success is not throwing
|
||||||
equal(opts.templates[0].source, 'a');
|
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() {
|
it('should handle different root', function(done) {
|
||||||
var opts = {templates: [__dirname + '/artifacts/empty.handlebars'], simple: true, root: 'foo/'};
|
var opts = {files: [__dirname + '/artifacts/empty.handlebars'], simple: true, root: 'foo/'};
|
||||||
Precompiler.loadTemplates(opts);
|
Precompiler.loadTemplates(opts, function(err, opts) {
|
||||||
equal(opts.templates[0].name, __dirname + '/artifacts/empty');
|
equal(opts.templates[0].name, __dirname + '/artifacts/empty');
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user