Skip to content

Instantly share code, notes, and snippets.

@creationix
Created July 9, 2010 01:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save creationix/468889 to your computer and use it in GitHub Desktop.
Save creationix/468889 to your computer and use it in GitHub Desktop.
Async Compiler
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);
});
});
});
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
@creationix
Copy link
Author

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