Created
July 9, 2010 01:12
-
-
Save creationix/468889 to your computer and use it in GitHub Desktop.
Async Compiler
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
var compiler = require('./asyncCompiler'), | |
fs = require('fs'); | |
compiler.helpers = { | |
partial: function (filename, data, callback) { | |
fs.readFile(filename, function (err, text) { | |
if (err) { callback(err); return; } | |
compiler(text, data, callback); | |
}); | |
} | |
} | |
var template = "Hello @planet, my name is @name() and I am @age() years old."; | |
var data = { | |
// Value | |
planet: "world", | |
// Async helper | |
name: function name(callback) { | |
process.nextTick(function () { | |
callback(null, "Tim Caswell"); | |
}); | |
}, | |
// Sync helper | |
age: function age() { | |
return 28; | |
} | |
}; | |
// Get the compiled template, and the execute it | |
var fn = compiler(template); | |
console.log("\nJavaScript"); | |
console.log(fn.toString()); | |
fn(data, function (err, text) { | |
console.log("OUTPUT " + text); | |
// Or do it in one shot | |
compiler(template, data, function (err, text) { | |
console.log("OUTPUT2 " + text); | |
// Or use a stream | |
var stream = new process.EventEmitter(); | |
fn(data, stream); | |
stream.addListener('data', function (data) { | |
console.log("DATA " + JSON.stringify(data.toString())); | |
}); | |
stream.addListener('end', function () { | |
console.log("END"); | |
}); | |
stream.addListener('error', function (err) { | |
console.log("ERROR " + err.stack); | |
}); | |
}); | |
}); |
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
JavaScript | |
function fn(locals, callback) { | |
locals.__proto__ = module.exports.helpers; | |
var position = 0, stream, chunks; | |
if (!(typeof callback === 'function')) { | |
if (callback instanceof process.EventEmitter) { | |
stream = callback; | |
callback = undefined; | |
} else { | |
throw new Error("Type Error: last argument must be either a callback function or stream instance"); | |
} | |
} | |
function check() { | |
var pieces = []; | |
while (chunks[position] && position < chunks.length) { | |
if (stream) { | |
pieces.push(chunks[position]); | |
} | |
position++; | |
} | |
if (stream && pieces.length > 0) { | |
stream.emit('data', new Buffer(pieces.join(""))); | |
} | |
if (position === chunks.length) { | |
if (callback) { | |
callback(null, new Buffer(chunks.join(""))); | |
} | |
if (stream) { | |
stream.emit('end'); | |
} | |
} | |
} | |
function execute(position, fn) { | |
try { | |
chunks[position] = fn(function (err, result) { | |
if (err) { | |
if (stream) stream.emit('error', err); | |
if (callback) callback(err); | |
return; | |
} | |
chunks[position] = result; | |
check(); | |
}); | |
} catch (err) { | |
if (stream) stream.emit('error', err); | |
if (callback) callback(err); | |
} | |
} | |
process.nextTick(function () { | |
with(locals) { | |
// START GENERATED CODE | |
chunks = new Array(5); | |
chunks[0] = "Hello " + planet + ", my name is "; | |
execute(1, name); | |
chunks[2] = " and I am "; | |
execute(3, age); | |
chunks[4] = " years old"; | |
check(); | |
// END GENERATED CODE | |
} | |
}); | |
} | |
OUTPUT Hello world, my name is Tim Caswell and I am 28 years old | |
OUTPUT2 Hello world, my name is Tim Caswell and I am 28 years old | |
DATA "Hello world, my name is " | |
DATA "Tim Caswell and I am 28 years old" | |
END |
if you wanted that though I suppose even with existing stuff like haml or jade, you could change the generated buf.push() calls to res.write(). dont get me wrong though im totally not against the idea, but until I have a practical need for it myself it is not worth implementing. I can see this being more useful for maybe feed generation or something along those lines where you could pipe the data through
Updated API per bradleymeck's suggestions on IRC
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
the chunking thing would be nice in some cases, but most user agents I have seen dont even output the chunks as they receive them, at least most browsers cant render