handlebar-rider
Advanced tools
Comparing version 0.1.13 to 0.1.20
@@ -10,2 +10,3 @@ // handlebar rider | ||
, async = require('async') | ||
, path = require('path') | ||
; | ||
@@ -18,78 +19,42 @@ | ||
in: './app/handlebars/', | ||
out: './public/javascript/templates.js', | ||
in : './app/handlebars/', | ||
out : './public/javascript/templates.js', | ||
templates: [], | ||
ext : ["hb","hbs","handlebars","template","templates","tpl","item","part","prt","pt"], | ||
minify: true | ||
ext : [], | ||
minify : true, | ||
force : false, | ||
strip : false, | ||
compact : false | ||
}; | ||
scli.config.appName("Handlebar-Rider"); | ||
// recursively reads in directory and namespaces template and partial objects | ||
var readTemplatesDirectory = function(dir, done) { | ||
// stores results | ||
var results = [] | ||
try { | ||
// read the directory | ||
fs.readdir(dir, function(err, list) { | ||
if (err) return done(err); | ||
var pending = list.length; | ||
if (!pending) return done(null, results); | ||
// walk it | ||
list.forEach( function(file) { | ||
file = dir + '/' + file; | ||
// determine if file or directory | ||
fs.stat(file, function(err, stat) { | ||
if (stat && stat.isDirectory()) { | ||
// push as directory | ||
results.push('directory:' + file); | ||
readTemplatesDirectory(file, function(err, res) { | ||
results = results.concat(res); | ||
fs.readdir(dir, function(err, list) { | ||
if (err) return done(err); | ||
var pending = list.length; | ||
if (!pending) return done(null, results); | ||
async.each(list, function(file) { | ||
file = dir + '/' + file; | ||
fs.stat(file, function(err, stat) { | ||
if(err) throw err; | ||
if (stat && stat.isDirectory()) { | ||
results.push({ type : 'directory', name : file }); | ||
readTemplatesDirectory(file, function(err, res) { | ||
results = results.concat(res); | ||
if (!--pending) done(null, results); | ||
}); | ||
} else if(stat && stat.isFile()) { | ||
results.push({ type : 'file', name : file }); | ||
if (!--pending) done(null, results); | ||
}); | ||
} else { | ||
// push as file | ||
results.push('file:' + file); | ||
if (!--pending) done(null, results); | ||
} | ||
} | ||
}); | ||
}); | ||
}); | ||
}); | ||
} catch(err) { | ||
scli.error(err); | ||
} | ||
}; | ||
var setupWatchTree = function(dir) { | ||
watch.watchTree(rider.in, function (f, curr, prev) { | ||
if (typeof f == "object" && prev === null && curr === null) { | ||
// Finished walking the tree | ||
} else if (prev === null) { | ||
// f is a new file | ||
} else if (curr.nlink === 0) { | ||
// f was removed | ||
} else { | ||
// f was changed | ||
} | ||
}, function () { | ||
}); | ||
}; | ||
var setupWatchMonitor = function(dir) { | ||
@@ -99,44 +64,20 @@ watch.createMonitor(dir, function (monitor) { | ||
// Handle file changes | ||
scli.log("Watcher detected change: created"); | ||
fileHasChanged(); | ||
scli.log("New file detected: '" + f + "'"); | ||
rider.templates = []; | ||
readAndCompile(); | ||
}); | ||
monitor.on("changed", function (f, curr, prev) { | ||
// Handle new files | ||
scli.log("Watcher detected change: changed"); | ||
fileHasChanged(); | ||
scli.log("File change detected: '" + f + "'"); | ||
rider.templates = []; | ||
readAndCompile(); | ||
}); | ||
monitor.on("removed", function (f, stat) { | ||
// Handle removed files | ||
scli.log("Watcher detected change: removed"); | ||
fileHasChanged(); | ||
scli.log("File removed: '" + f + "'"); | ||
rider.templates = []; | ||
readAndCompile(); | ||
}); | ||
}); | ||
}; | ||
//watches a file for changes | ||
var fileHasChanged = function(event, filename){ | ||
scli.log("Change detected to file '" + filename + "'"); | ||
compileTemplates(); | ||
}; | ||
// watches a directory for changes | ||
var directoryHasChanged = function(event, filename){ | ||
scli.log('New or removed file "' + filename + '" detected, recompiling'); | ||
readAndCompile(rider.in, rider.watch); | ||
}; | ||
var watchers = [] | ||
var unwatchAll = function(){ | ||
for(var w = 0; w < watchers.length; w++){ | ||
watchers[w].close(); | ||
} | ||
} | ||
@@ -150,158 +91,111 @@ var precompile = function(data) { | ||
}; | ||
//compiles to output destination | ||
var compileTemplates = function(){ | ||
scli.log("Compiling templates now!"); | ||
var processedFiles = []; | ||
var errors = false; | ||
try { | ||
output = ['(function() {']; | ||
output.push('\n var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};\n'); | ||
// todo - figure out cleaner way to register partials as actual partials | ||
output.push('\n Handlebars.partials = Handlebars.templates;\n') | ||
for(var t = 0; t < rider.templates.length; t++){ | ||
processedFiles.push(rider.templates[t].namespace); | ||
data = fs.readFileSync(rider.templates[t].file, 'utf8'); | ||
// clean the data a bit | ||
data = data.replace(/<!--(.*?)-->/gm, "") | ||
.replace(/(\r\n|\n|\r)/gm,""); | ||
// check for partial conventions | ||
if (rider.templates[t].namespace.indexOf('/_') > 0){ | ||
compiled = 'templates[\'' + rider.templates[t].namespace.replace(/\/_/,'_') + '\'] = template(' + precompile(data) + ');\n' | ||
output = ["(function() {"]; | ||
output.push("\n var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};\n"); | ||
// todo - figure out cleaner way to register partials as actual partials | ||
output.push('\n Handlebars.partials = Handlebars.templates;\n'); | ||
async.each(rider.templates, function(template, nextTemplate) { | ||
fs.readFile(template.file, 'utf8', function(err, data) { | ||
var compiled; | ||
processedFiles.push(template.namespace); | ||
// We only run the painfully long regex if the user REALLY wants us to AND it's not being minified. Minifying strips this for us :) | ||
if(rider.strip && !rider.minify) | ||
data = data.replace(/<!--(.*?)-->/gm, "").replace(/(\r\n|\n|\r)/gm,""); | ||
// check for partial conventions | ||
if (template.namespace.indexOf('/_') > 0){ | ||
compiled = 'templates[\'' + template.namespace.replace(/\/_/,'_') + '\'] = template(' + precompile(data) + ');\n'; | ||
} else if( template.namespace.indexOf('partial') != 0 ) { | ||
compiled = 'templates[\'' + template.namespace + '\'] = template(' + precompile(data) + ');\n'; | ||
} else { | ||
compiled = 'templates[\'' + template.namespace.replace(/partials\//,'') + '\'] = template(' + precompile(data) + ');\n'; | ||
} | ||
output.push(compiled); | ||
nextTemplate(); | ||
}); | ||
}, function(err) { | ||
if(err) throw err; | ||
//complete output array to single string | ||
output.push('})();'); | ||
output = output.join(''); | ||
} else if( rider.templates[t].namespace.indexOf('partial') != 0 ) { | ||
compiled = 'templates[\'' + rider.templates[t].namespace + '\'] = template(' + precompile(data) + ');\n' | ||
} else { | ||
compiled = 'templates[\'' + rider.templates[t].namespace.replace(/partials\//,'') + '\'] = template(' + precompile(data) + ');\n' | ||
} | ||
output.push(compiled); | ||
if(rider.minify){ | ||
var ast = uglify.parser.parse(output); | ||
ast = uglify.uglify.ast_mangle(ast); | ||
ast = uglify.uglify.ast_squeeze(ast); | ||
output = uglify.uglify.gen_code(ast); | ||
} | ||
} catch(e) { | ||
var filename = processedFiles.pop(); | ||
errors = true; | ||
scli.error('Compile Failure while processing "' + filename + '"'); | ||
} | ||
if(errors) { | ||
return false; | ||
} | ||
//complete output array to single string | ||
output.push('})();'); | ||
output = output.join(''); | ||
if(rider.minify){ | ||
var ast = uglify.parser.parse(output); | ||
ast = uglify.uglify.ast_mangle(ast); | ||
ast = uglify.uglify.ast_squeeze(ast); | ||
output = uglify.uglify.gen_code(ast); | ||
} | ||
//write the output file | ||
try { | ||
fs.writeFileSync(rider.out, output, 'utf8'); | ||
scli.ok('Compiled ' + processedFiles.length + ' templates in "' + rider.in + '" to "' + rider.out + '"'); | ||
} catch(e){ | ||
scli.error('ERROR! destination file or directory does not exist.', e); | ||
} | ||
//write the output file | ||
fs.exists(rider.out, function(exists) { | ||
if(exists) { | ||
fs.writeFile(rider.out, output, 'utf8', function(err) { | ||
if(err) throw "Unable to write the output file! Make sure your permissions are correct and try again!"; | ||
scli.ok('Compiled ' + processedFiles.length + ' templates in "' + rider.in + '" to "' + rider.out + '".'); | ||
}); | ||
} else { | ||
throw error('The output file "' + rider.out + '" does not exist. Double check it!'); | ||
} | ||
}); | ||
}); | ||
}; | ||
} catch(err) { | ||
var filename = processedFiles.pop(); | ||
scli.error('Compile Failure while processing "' + filename + '". Exiting without writing to output file.', err); | ||
return false; | ||
} | ||
}; | ||
var readAndCompile = function(dir, watch){ | ||
rider.templates = [] | ||
// unwatch all the files | ||
unwatchAll(); | ||
//read files in the directory | ||
readTemplatesDirectory(dir, function(err, files) { | ||
// sort filenames to preserve ordering in generated files (so that re-running the script does not produce different md5 sigature) | ||
files = files || ""; | ||
if(__.size(files) <= 0 ) { | ||
scli.error('There are no files for Handlebar-Rider to compile. Did you run the command correctly?'); | ||
return false; | ||
} | ||
files.sort(); | ||
try { | ||
if(err) | ||
throw new Error('directory does not exist: ' + dir) | ||
for(var f = 0; f < files.length; f++){ | ||
// determine whether or not it's a file or directory. | ||
info = files[f].split(':') | ||
if( info[0] == 'file' && (info[1].indexOf('.hb') > 0 || info[1].indexOf('.handlebars') > 0) ){ | ||
/* | ||
// watch the file | ||
if(watch) { | ||
//fs.unwatchFile(info[1], null) | ||
watchers.push(fs.watch(info[1], fileHasChanged)) | ||
} | ||
*/ | ||
// get the template namespace by using the extra directory | ||
template_dir = rider.in.toString(); | ||
file_and_dir = info[1].substr( (info[1].indexOf(template_dir) + template_dir.length) + 1, info[1].length); | ||
namespaced = file_and_dir.replace(/\.hb/,''); | ||
// push object for the compiler to work with | ||
rider.templates.push({ | ||
namespace: namespaced, | ||
file: info[1] | ||
}) | ||
} else if ( info[0] == 'directory') { | ||
/* | ||
// watch the directory for new / removed files | ||
if(watch){ | ||
//fs.unwatchFile(info[1], null) | ||
watchers.push(fs.watch(info[1], directoryHasChanged)) | ||
} | ||
*/ | ||
var readAndCompile = function(dir){ | ||
dir = dir || rider.in; | ||
fs.exists(dir, function(exists) { | ||
try { | ||
if(!exists) throw "The input directory '" + dir + "' does not exist! Maybe give that a second look."; | ||
readTemplatesDirectory(dir, function(err, files) { | ||
// sort filenames to preserve ordering in generated files (so that re-running the script does not produce different md5 sigature) | ||
if(__.size(files) <= 0 ) { | ||
throw error('There are no files for Handlebar-Rider to compile. Did you run the command correctly?'); | ||
} else { | ||
async.each(files.sort(), function(file, nextFile) { | ||
if(file.type == 'file') { | ||
var ext = path.extname(file.name); | ||
if(needsCompile(ext)) { | ||
var relpath = path.relative(rider.in, file.name); | ||
var newTemplate = { | ||
namespace : relpath.replace(ext,''), | ||
file : file.name | ||
}; | ||
rider.templates.push(newTemplate); | ||
} | ||
} | ||
nextFile(); | ||
}, function(err) { | ||
if(err) throw err; | ||
compileTemplates(); | ||
}); | ||
} | ||
} | ||
compileTemplates(); | ||
} catch (e){ | ||
scli.error('ERROR! check to be sure your directories exist. ', e ); | ||
scli.log('input directory: ' + dir); | ||
scli.log('destination file: ' + rider.out); | ||
}); | ||
} catch(err) { | ||
scli.error(err); | ||
if(rider.help) | ||
scli.log(rider.help) | ||
} | ||
}; | ||
}); | ||
} | ||
}; | ||
var needsCompile = function(ext) { | ||
if( rider.force || __.contains(rider.ext, ext)) | ||
return true; | ||
else | ||
return false; | ||
}; | ||
// runs the command line | ||
exports.run = function(){ | ||
//get options specified on command line | ||
@@ -325,3 +219,12 @@ argv = optimist | ||
.describe('e','Add more extensions to the defaults for templates that Handlebar-Rider will compile') | ||
.default('e','["hb","hbs","handlebars","template","templates","tpl","item","part","prt","pt"]') | ||
.default('e',['.hb','.hbs','.handlebars']) | ||
.alias('f','force') | ||
.describe('f','Forces all files found in the input directory to be compiled. Performance gains are not unheard of here.') | ||
.default('f', false) | ||
.alias('s','strip') | ||
.describe('s','Strip all comments from templates to clean up un-minified output') | ||
.default('s', false) | ||
.alias('c','compact') | ||
.describe('c','Hides the application name in command line logging for a more compact view') | ||
.default('c', true) | ||
.argv | ||
@@ -334,10 +237,28 @@ | ||
rider.watch = argv.watch; | ||
rider.help = optimist.help() | ||
rider.force = argv.force; | ||
rider.strip = argv.strip; | ||
rider.help = optimist.help(); | ||
rider.compact = argv.compact; | ||
if(rider.compact) | ||
scli.config.hideName(); | ||
else | ||
scli.config.appName("Handlebar-Rider"); | ||
if(rider.watch) { | ||
scli.warn('Watching template directory "' + dir + '"'); | ||
setupWatchTree(dir); | ||
scli.log('Watching template directory "' + dir + '"'); | ||
setupWatchMonitor(dir); | ||
} | ||
readAndCompile(dir, rider.watch); | ||
if(rider.force) | ||
scli.warn("ALL files under the input folder, '" + rider.in + "', will be compiled, regardless of extension!"); | ||
if( argv.extensions && !rider.force ) { | ||
__.each(argv.extensions, function(ext) { | ||
rider.ext.push(ext); | ||
}); | ||
scli.warn("All files of the following types will be compiled: " + rider.ext.join(", ")); | ||
} | ||
readAndCompile(dir); | ||
@@ -349,7 +270,6 @@ } | ||
exports.watch = function(){ | ||
scli.warn('Watching template directory "' + rider.in + '"'); | ||
rider.watch = true; | ||
readAndCompile(rider.in, true); | ||
setupWatchMonitor(rider.in); | ||
readAndCompile(rider.in); | ||
} | ||
@@ -360,6 +280,3 @@ | ||
readAndCompile(rider.in, false); | ||
} | ||
})() |
@@ -5,3 +5,3 @@ { | ||
"description" : "Compiles/watches a directory of handlebar templates files and precompiles into single js output file", | ||
"version" : "0.1.13", | ||
"version" : "0.1.20", | ||
@@ -23,3 +23,3 @@ "repository" : { | ||
"engines" : { | ||
"node" : ">= 0.4.9" | ||
"node" : ">= 0.8.0" | ||
}, | ||
@@ -34,4 +34,5 @@ | ||
"watch" : "*", | ||
"async" : "*" | ||
"async" : "*", | ||
"path" : "*" | ||
} | ||
} |
@@ -9,2 +9,4 @@ # handlebar-rider | ||
UPDATE 2.25.2013 - @piercemoore has contributed some AMAZING updates to this project available on the command line. | ||
UPDATE 9.20.2012 - I have merged this library with Flint (http://github.com/cif/flint) however, changes contributed by others are welcome and always merged. | ||
@@ -21,9 +23,12 @@ | ||
Options: | ||
-i, --in Specify an input templates directory [default: "./app/handlebars/"] | ||
-o, --out Specify an output file into which templates are compiled [default: "./public/javascript/templates.js"] | ||
-w, --watch Watch your handlebars files and compile when changes occur [default: false] | ||
-r, --readable Make the output more readable by avoiding default minification [default: false] | ||
-i, --in Specify an input templates directory [default: "./app/handlebars/"] | ||
-o, --out Specify an output file into which templates are compiled [default: "./public/javascript/templates.js"] | ||
-w, --watch Watch your handlebars files and compile when changes occur [default: false] | ||
-r, --readable Make the output more readable by avoiding default minification [default: false] | ||
-e, --extensions Add more extensions to the defaults for templates that Handlebar-Rider will compile [default: [".hb",".hbs",".handlebars"]] | ||
-f, --force Forces all files found in the input directory to be compiled. Performance gains are not unheard of here. [default: false] | ||
-s, --strip Strip all comments from templates to clean up un-minified output [default: false] | ||
-c, --compact Hides the application name in command line logging for a more compact view [default: true] | ||
## npm module usage | ||
@@ -30,0 +35,0 @@ |
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
Found 1 instance in 1 package
13932
6
82
0
8
258
6
2
1
+ Addedpath@*
+ Addedinherits@2.0.3(transitive)
+ Addedpath@0.12.7(transitive)
+ Addedprocess@0.11.10(transitive)
+ Addedutil@0.10.4(transitive)