mlzboy
5/29/2010 - 3:24 AM

ejs.js

/* Ejs parser for Nodejs
*
* Copyright (c) 2009, Howard Rauscher
* Licensed under the MIT License
*/

// PUBLIC METHODS
function parse(input) {
    var output = [];
    var innerOutput = [];
    var isEval = false;
    
    output.push('(function() {\nvar output = [];');
    for(var i = 0, len = input.length; i < len; i++) {
        var chr = input[i];
        if(isEval) {
            if(chr === '%' && input[i+1] === '>') {
                i++;
                isEval = false;
                output.push(new EvalString(innerOutput.join('')));
                innerOutput = [];
            }
            else {
                innerOutput.push(chr);
            }
        }
        else {
            if(chr === '<' && input[i+1] === '%') {
                i++;
                isEval = true;
                output.push(new LiteralString(innerOutput.join('')));
                innerOutput = [];
            }
            else {
                innerOutput.push(chr);
            }
        }
    }
    if(isEval) {
        output.push(new EvalString(innerOutput.join('')));
    }
    else {
        output.push(new LiteralString(innerOutput.join('')));
    }
    innerOutput = [];
    
    output.push('return output.join(\'\');\n})();');
    
    return output.join('\n');
}

// HELPERS
function escapeString(src) {
    return src
            .replace(escapeString.ESCAPE, '\\$1')
            .replace(escapeString.LINE_FEED, "\\n")
            .replace(escapeString.CARRIAGE_RETURN, "\\r");
}
escapeString.ESCAPE = /(["'\\])/g;
escapeString.LINE_FEED = /\n/g;
escapeString.CARRIAGE_RETURN = /\r/g;

// OBJECTS
function LiteralString(value) {
    this.value = value;
}
LiteralString.prototype.toString = function() {
    return 'output.push("'+escapeString(this.value)+'");';
};

function EvalString(value) {
    this.value = value;
    this.print = (value[0] === '=');
    this.include_trailing_line_feed = (value[value.length - 1] !== '-');
    
    if(this.print) {
        this.value = this.value.substring(1);
    }
    if(!this.include_trailing_line_feed) {
        this.value = this.value.substring(0, this.value.length - 1);
    }
}
EvalString.prototype.toString = function() {
    if(this.print) {
        return 'output.push('+this.value+');';
    }
    else {
        return this.value;
    }
    
};

exports.parse = parse;
<h1><%= title %></h1>
<ul>
<% users.forEach(function(user) { %>
    <li><%= user.name %></li>
<% }); %>
</ul>
var sys = require('sys'),
    posix = require('posix'),
    ejs = require('./ejs');
    
posix.cat('example.html.ejs').addCallback(function(content) {
    var title = 'Erb Example';
    var users = [{
        id : 1,
        name : 'John Does'
    }, {
        id : 2,
        name : 'Howard Rauscher'
    }];

    sys.puts(eval(ejs.parse(content)));
});