Last active
December 26, 2015 04:29
-
-
Save nickjacob/7093743 to your computer and use it in GitHub Desktop.
Newer version of my mini templating
This file contains hidden or 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 (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