Skip to content

Instantly share code, notes, and snippets.

@nickjacob
Last active December 26, 2015 04:29
Show Gist options
  • Save nickjacob/7093743 to your computer and use it in GitHub Desktop.
Save nickjacob/7093743 to your computer and use it in GitHub Desktop.
Newer version of my mini templating
;(function (window, document, undefined) {
var m = window.micro = {},
whiteSpaceRxp = /[\r\n\t\s]/g,
quotesRxp = /['"]/g,
attrRxp = /<%=\s*([\w_\$\.]+)\s*%>/ig;
// Convert template to use consistent quotes, remove unnecessary whitespace
// returns: the normalized template string
function normalizeTemplate(tpl) {
return tpl.replace(whiteSpaceRxp, ' ').replace(quotesRxp, "'");
}
// shortcut for quoting a string;
// this is for interpolation of `str` into the
// function body of the compiled template
function quote(str) {
return '"' + str + '"';
}
// a helper to produce a ternary expression;
// useful within the template (see use in typeTest);
// could allow us to create directives for if/else, although
// true statements would require tokens etc.
function ternary(test, ifTrue, ifFalse) {
return '((' + test + ') ? (' + ifTrue + ') : (' + ifFalse + '))';
}
// tests the property using typeof(), wraps
// the `ternary` helper
function typeTest(prop, typ, ifTrue, ifFalse) {
return ternary('typeof(' + prop + ') === ' + quote(typ), ifTrue, ifFalse);
}
// replace any attribute interpolations
// with actual string interpolation and a test
// to see if the attribute is a function (if it is,
// call the function with the object
// as context and first parameter
function attrReplace($0, prop) {
return '" +' + typeTest(prop, 'function', prop + '.call(this, this)', prop) + '+ "';
}
// we actually are going to use an IIFE
// within the generated function to reduce context
// to the object itself; safer and allows for more flexibility
function innerClosure(body) {
return 'return (function(){ ' + body + '}).call(obj)';
}
// produce a dynamically-generated function object using a `with` statement
// to produce a scope within the object; makes it easier to use props and
// safer since we mess w/ the context
function buildFn(body) {
return Function(['obj'], innerClosure(' with (this) { return ' + quote(body) + ' } '));
}
// @public function; compile a template using a DOM element, raw string,
// or a jQuery selector (hence the `html()` option); returns a Function
m.compile = function (tpl) {
tpl = typeof tpl === 'string' ? tpl : (tpl.innerHTML || tpl.html());
return buildFn(normalizeTemplate(tpl).replace(attrRxp, attrReplace));
}
}(window, window.document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment