Last active
August 29, 2015 14:21
-
-
Save linstantnoodles/176d232b10579ec7503c to your computer and use it in GitHub Desktop.
compiler
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, undefined) { | |
var directiveFactories = {}; | |
/** | |
* @description Register directive factory functions | |
* | |
* @param {String} name Name of the directive | |
* @param {Function} factory The factory function | |
*/ | |
function directive (name, factory) { | |
directiveFactories[name] = factory; | |
} | |
/** | |
* @description Compile directives | |
* | |
* @param {Node} node The root HTML node on which compilation starts | |
* @returns {Function} The final combined linking function | |
*/ | |
function compile (node) { | |
// Kick off with the root node | |
return compileNodes([node]); | |
/** | |
* @description Compile a list of nodes | |
* | |
* @param {Array|HTMLCollection} nodeList A list of HTML nodes | |
* @returns {Function} A combined linking function | |
*/ | |
function compileNodes (nodeList) { | |
// Stack for holding parent-child linker pairs | |
var linkers = []; | |
for (var i = 0; i < nodeList.length; i++) { | |
var node = nodeList[i]; | |
var directives = collectDirectives(node); | |
var linker = compileDirectives(node, directives); | |
// Recursively get combined linking function for its children | |
var childLinker = compileNodes(node.children); | |
linkers.push(linker); | |
linkers.push(childLinker); | |
} | |
return combinedLinker; | |
/** | |
* @description Invoke all the linkers | |
*/ | |
function combinedLinker () { | |
for (var i = 0; i < linkers.length; i += 2) { | |
var currLinker = linkers[i]; | |
var childLinker = linkers[i+1]; | |
currLinker(childLinker); | |
} | |
} | |
} | |
/** | |
* @description Get and sort directives on node | |
* | |
* @param {Node} node A HTML node | |
* @return {Array.<Object>} A list of directives | |
*/ | |
function collectDirectives (node) { | |
var suffix = "-dir"; | |
var directives = []; | |
for (var i = 0; i < node.attributes.length; i++) { | |
var attrName = node.attributes[i].name; | |
if (attrName.indexOf(suffix) >= 0) { | |
var directiveFactory = directiveFactories[attrName]; | |
if (directiveFactory) { | |
var directive = directiveFactory(); | |
// Set default priority | |
directive['priority'] = directive['priority'] || 0; | |
directives.push(directive); | |
} | |
} | |
} | |
// Higher priority directives come first | |
directives.sort(function (directiveA, directiveB) { | |
return directiveB.priority - directiveA.priority; | |
}); | |
return directives; | |
} | |
/** | |
* @description Compile the directives to get linking functions (pre and post) | |
* | |
* @param {Node} node A HTML node | |
* @param {Array} directives A list of directives | |
* @return {Function} Linking function | |
*/ | |
function compileDirectives (node, directives) { | |
var preLinks = []; | |
var postLinks = []; | |
for (var i = 0; i < directives.length; i++) { | |
var links = directives[i].compile(); | |
preLinks.push(links.pre); | |
postLinks.push(links.post); | |
} | |
return linker; | |
/** | |
* @description Executes the current nodes linking functions as well as | |
* the linking functions of its children | |
* | |
* @param {Function} childLinker The combined linking function | |
* from the compilation of the current nodes children | |
*/ | |
function linker (childLinker) { | |
// Run prelink functions in pre-order stage | |
for (var i = 0; i < preLinks.length; i++) { | |
preLinks[i](node); | |
} | |
// Run child links | |
childLinker(); | |
// Run postlink functions in post-order stage | |
for (var i = 0; i < postLinks.length; i++) { | |
postLinks[i](node); | |
} | |
} | |
} | |
} | |
// Define API | |
window.Compiler = { | |
directive: directive, | |
compile: compile | |
}; | |
})(window); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment