Created
June 17, 2010 18:44
-
-
Save morganrallen/442553 to your computer and use it in GitHub Desktop.
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
(function(glob) { | |
/* | |
stpl | |
Morgan "ARR!" Allen | |
morganrallen@gmail.com | |
supports simple replacements | |
<li>${var}</li> + { var: "val" } = <li>val</li> | |
simple replacement with default value | |
<li>${var!"default value"}</li> + {} = <li>default value</li> | |
optional replacements | |
<ul>${var[<li>${var}</li>]}</ul> + { var: "val" } = <ul><li>val</li></ul> | |
<ul>${var[<li>${var}</li>]}</ul> + { foo: "bar" } = <ul></ul> | |
arrays and object | |
<ul>${[array[<li id="$i">$el</li>]]}</ul> + [ "zero", "one", "two" ] = <ul><li id="0">zero</li><li id="1">one</li><li id="2">two</li></ul> | |
<ul>${[array{<li id="$i">$el</li>}]}</ul> + [ 0:"zero", 1:"one", 2:"two" ] = <ul><li id="0">zero</li><li id="1">one</li><li id="2">two</li></ul> | |
***** | |
Note the subtle difference between Arrays and Objects; | |
${[Array[ <<<<<<<< | |
${[Object{ <<<<<<<< | |
I'd prefer them the same (maybe) but have not figured out the expression | |
object property replacements | |
<li>${var.prop.var}</li> + { var: { prop: { var: "val" } } } = <li>val</li> | |
special methods | |
<div class="container">${include(another.tpl)}</div> | |
*/ | |
var rxDefaultValue = /\${.+!\"(.+)\"}/g, | |
rxListMatch = /\${\[(\w+)([{?\[?])([<>a-zA-Z0-9=\"\'\ \$\/\-_]+)([\]?}?])\]}/mi, | |
rxOptional = /\$\{(\w+)\[([a-zA-Z0-9"'<>\/\${}=\ \-\r\n]+)\]}/gmi, | |
rxRemoveOrphans = /\$\{\w+(?:!)?(?:\"(.+)\")?\}/g, | |
rxSpecialMethods = /\$\{(\w+)/g, | |
rxSubstitue = [ | |
"\\${", | |
"(?:!)?(?:\"(.+)\")?}", | |
"g" | |
]; | |
function processTemplate(tpl, attrs, leaveOrphans) { | |
// replace all the holders in the template. | |
var attr, m; | |
// optionals are blocks that will appear only if a variable is present | |
// $[varname[<div>content block]] | |
while(m = tpl.match(rxOptional)) { | |
if(m[1] && attrs[m[1]]) { | |
tpl = tpl.replace(rxOptional, m[2]); | |
} else { | |
tpl = tpl.replace(rxOptional, ''); | |
} | |
} | |
while(m = tpl.match(rxListMatch)) { | |
if(!m[1] || !m[3]) { | |
tpl = tpl.replace(m[0], ''); | |
} else if(attrs[m[1]]) { | |
var i, replacement = ""; | |
if(m[2] == "[") | |
for(i = 0; i < attrs[m[1]].length; i++) | |
replacement += m[3].replace('$i', i).replace('$el', attrs[m[1]][i]); | |
else if(m[2] == "{") | |
for(i in attrs[m[1]]) | |
replacement += m[3].replace("$i", i).replace("$el", attrs[m[1]][i]); | |
tpl = tpl.replace(m[0], replacement); | |
} | |
} | |
for(attr in attrs) { | |
// if you want any of these, specify as a string ( "undefined", "false", "null" ) | |
if(attr === undefined || attr === false || attr === null) { | |
attr = ""; | |
} | |
// default values can be specified | |
// ${variableName!"default value"} | |
// || "$1" matches for undefined | |
tpl = tpl.replace(new RegExp(rxSubstitue[0] + attr + rxSubstitue[1], rxSubstitue[2]), attrs[attr] || "$1"); | |
} | |
// matches if key was not declared | |
tpl = tpl.replace(rxDefaultValue, "$1"); | |
// find . (dot) denoted object properties | |
// I really don't like this solution.... | |
var rxObjProps = /\${((?:(\w+)\.?)+)?}/, | |
m = rxObjProps.exec(tpl), v; | |
if(m && attrs[m[1][0]]) { | |
m = m[1].split("."); | |
v = attrs[m.shift()]; | |
while(m.length > 0) { | |
v = v[m.shift()]; | |
} | |
tpl = tpl.replace(rxObjProps, v); | |
} | |
var rxSpecialMethods = /\$\{(\w+)\((.*)\)\}/, | |
foundSpecial = false; | |
while(m = tpl.match(rxSpecialMethods)) { | |
if(!processTemplate.special[m[1]]) { | |
tpl = tpl.replace(rxSpecialMethods, ''); | |
continue; | |
} | |
foundSpecial = true; | |
var args = m[2].replace(/\ +,\ +/, ",").split(","); | |
tpl = tpl.replace(rxSpecialMethods, processTemplate.special[m[1]].apply(null, args)); | |
} | |
if(foundSpecial) | |
return processTemplate(tpl, attrs); | |
// remove orphans | |
if(leaveOrphans !== true) { | |
tpl = tpl.replace(rxRemoveOrphans, ''); | |
} | |
return tpl; | |
}; | |
processTemplate.special = {}; | |
if(glob.window && (glob.window === glob)) | |
glob.stpl = { | |
processTemplate: processTemplate | |
}; | |
else | |
glob.processTemplate = processTemplate; | |
})(this); |
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
<html> | |
<head> | |
<script src="stpl.js" type="text/javascript"></script> | |
<script src="test.js" type="text/javascript"></script> | |
</head> | |
</html> |
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
if(!this.window) { | |
var stpl = require("./stpl"), | |
sys = require("sys"); | |
} else { | |
var stpl = { | |
processTemplate: processTemplate | |
}, | |
sys = { | |
puts: function(msg) { console.log(msg); } | |
}; | |
}; | |
stpl.processTemplate.special.include = function(tpl) { | |
return "blahblah"; | |
} | |
stpl.processTemplate.special.add = function(x, y) { | |
return Number(x) + Number(y); | |
} | |
sys.puts("special methods (include):\n" + stpl.processTemplate("<div>${include(${template})}</div>", {template: 'test.tpl'})); | |
sys.puts("special methods (addition):\n" + stpl.processTemplate("<div>${add(${x} , ${y})}</div>", {x:40, y:2})); | |
sys.puts("simple:\n" + stpl.processTemplate('<span>${vr}</span>', {vr:"val"})); | |
sys.puts("dotted:\n" + stpl.processTemplate('<span>${v.r}</span>', {v:{r:"val"}})); | |
sys.puts("default:\n" + stpl.processTemplate('<span>${vr!"default value"}</span>', {})); | |
sys.puts("optional (valid):\n" + stpl.processTemplate('<ul>${vr[<li>'+ | |
'${vr}</li>]}</ul>', {vr:"val"})); | |
sys.puts("optional: (invalid):\n" + stpl.processTemplate('<ul>${vr[<li>${vr}</li>]}</ul>', {foo:"val"})); | |
sys.puts("array list:\n" + stpl.processTemplate('<ul>${[array[<li id="$i">$el</li>]]}</ul>', {array:["one", "two", "three"]})); | |
sys.puts("object list:\n" + stpl.processTemplate('<ul>${[object{<li id="$i">$el</li>}]}</ul>', {object:{one:"one", two:"two", three:"three"}})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment