Skip to content

Instantly share code, notes, and snippets.

@bmeck
Created September 14, 2010 03:33
Show Gist options
  • Save bmeck/578481 to your computer and use it in GitHub Desktop.
Save bmeck/578481 to your computer and use it in GitHub Desktop.
(function(){
//pistachio
//fear the stachio
function compile(source,opts) {
source = String(source)
opts = opts || {}
var template_source = ""
var matcher = /[{][{]([@])?([#])?([/])?([a-zA-Z_$]\w*|[.])([\[](-?\d+)?(..(-?\d+)?)?[\]])?[}][}]/g
var index = 0
var match;
var need_context = false
var need_template = false
var need_iteration = false
var need_locals = false
var context_depth = 0
var context_allocated_depth = 0
var iteration_depth = 0
var iteration_allocated_depth = 0
var ender_stack=[]
var defaulted_value = opts.default_value ? "||"+JSON.stringify(opts.default_value) : ""
while(match = matcher.exec(source)) {
if(index !== match.index)
template_source += "stream.write("+JSON.stringify(source.slice(index,match.index))+");"
var target = ""
var obj = match[4]
index = matcher.lastIndex
//template
if(match[1]) {
need_template = true
target = "template_table."+obj
template_source += "tmp="+target+";"
template_source +=
"typeof tmp ==='function'?tmp(c0,template_table,stream):("+target+"=compile("+target+",opts))(c0,template_table,stream);"
continue;
}
//with
else if (match[2]) {
need_context = true
context_depth++
if(context_depth > context_allocated_depth) context_allocated_depth = context_depth
template_source += "c"+context_depth+"=c"+(context_depth-1)+"."+obj+";"
ender_stack.push(false)
continue
}
//close
else if (match[3]) {
var alter = ender_stack.pop()
if(alter) {
template_source += alter[0]
context_depth -= alter[1]
}
else {
context_depth--;
}
continue
}
//iteration
else if (match[5]) {
//start
need_context = true
need_iteration = true
var start = Number(match[6]||0)
var end = match[7] ? match[8] ? Number(match[8]) : null : start
if(start == end) {
context_depth++
if(context_depth > context_allocated_depth) context_allocated_depth = context_depth
var cindex
if(start < 0) cindex = "c"+(context_depth-1)+"."+obj+".length"+start
else cindex = start
template_source += "c"+context_depth+"=c"+(context_depth-1)+"."+obj+"["+cindex+"];"
ender_stack.push(false)
console.log(match)
}
else {
var l = "l"+iteration_depth
var i = "i"+iteration_depth
context_depth++
iteration_depth++
if(iteration_depth > iteration_allocated_depth) iteration_allocated_depth = context_depth
if(end) {
if(end < 0) end = "c"+context_depth+".length"+(end===null||end==0?"":end)
}
else {
end = "c"+context_depth+".length"
}
template_source += "c"+context_depth+"=c"+(context_depth-1)+"."+obj+";";
template_source += l+"="+end+";"
if(start < 0) start = l+start
context_depth++
if(context_depth > context_allocated_depth) context_allocated_depth = context_depth
template_source += "for("+i+"="+start+";"+i+"<"+l+";++"+i+"){"
template_source += "c"+context_depth+"=c"+(context_depth-1)+"["+i+"];";
ender_stack.push(["}",2])
}
continue
//end
}
else if (obj === ".") {
template_source+="stream.write(c"+context_depth+defaulted_value+");"
continue
}
else {
need_locals = true
for(var i=context_depth;i>0;i--) {
var context_var = "c"+i
target+="\""+obj +"\" in "+context_var+"?"+context_var+"."+obj+":";
}
target += "c0."+obj+""
}
template_source += "stream.write("+target+defaulted_value+");"
}
if(index !== source.length)
template_source += "stream.write("+JSON.stringify(source.slice(index))+");"
var pre = ""
//if(need_locals) pre+="c0=c0||{};"
//if(need_template) pre+="template_table=template_table||{};var tmp;"
if(need_context) while(context_allocated_depth > 0) pre+="var c"+(context_allocated_depth--)+";"
if(need_iteration) while(iteration_allocated_depth > 0) pre+="var i"+(iteration_allocated_depth)+";"+"var l"+(iteration_allocated_depth--)+";"
console.log(pre+template_source)
var render = Function("compile","opts","return function(c0,template_table,stream){"+pre+template_source+"}")(compile,opts)
render.source = template_source
return render
}
if(typeof module !== "undefined") module.exports = compile
if(window) window.pistachio = {compile : compile}
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment