diff options
Diffstat (limited to 'testing/web-platform/tests/html/syntax/parsing/template.js')
-rw-r--r-- | testing/web-platform/tests/html/syntax/parsing/template.js | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/syntax/parsing/template.js b/testing/web-platform/tests/html/syntax/parsing/template.js new file mode 100644 index 0000000000..b249fb64c7 --- /dev/null +++ b/testing/web-platform/tests/html/syntax/parsing/template.js @@ -0,0 +1,214 @@ + /* + * Template code + * + * A template is just a javascript structure. An element is represented as: + * + * [tag_name, {attr_name:attr_value}, child1, child2] + * + * the children can either be strings (which act like text nodes), other templates or + * functions (see below) + * + * A text node is represented as + * + * ["{text}", value] + * + * String values have a simple substitution syntax; ${foo} represents a variable foo. + * + * It is possible to embed logic in templates by using a function in a place where a + * node would usually go. The function must either return part of a template or null. + * + * In cases where a set of nodes are required as output rather than a single node + * with children it is possible to just use a list + * [node1, node2, node3] + * + * Usage: + * + * render(template, substitutions) - take a template and an object mapping + * variable names to parameters and return either a DOM node or a list of DOM nodes + * + * substitute(template, substitutions) - take a template and variable mapping object, + * make the variable substitutions and return the substituted template + * + */ + + function is_single_node(template) + { + return typeof template[0] === "string"; + } + + function substitute(template, substitutions) + { + if (typeof template === "function") { + var replacement = template(substitutions); + if (replacement) + { + var rv = substitute(replacement, substitutions); + return rv; + } + else + { + return null; + } + } + else if (is_single_node(template)) + { + return substitute_single(template, substitutions); + } + else + { + return filter(map(template, function(x) { + return substitute(x, substitutions); + }), function(x) {return x !== null;}); + } + } + expose(substitute, "template.substitute"); + + function substitute_single(template, substitutions) + { + var substitution_re = /\${([^ }]*)}/g; + + function do_substitution(input) { + var components = input.split(substitution_re); + var rv = []; + for (var i=0; i<components.length; i+=2) + { + rv.push(components[i]); + if (components[i+1]) + { + rv.push(substitutions[components[i+1]]); + } + } + return rv; + } + + var rv = []; + rv.push(do_substitution(String(template[0])).join("")); + + if (template[0] === "{text}") { + substitute_children(template.slice(1), rv); + } else { + substitute_attrs(template[1], rv); + substitute_children(template.slice(2), rv); + } + + function substitute_attrs(attrs, rv) + { + rv[1] = {}; + for (name in template[1]) + { + if (attrs.hasOwnProperty(name)) + { + var new_name = do_substitution(name).join(""); + var new_value = do_substitution(attrs[name]).join(""); + rv[1][new_name] = new_value; + }; + } + } + + function substitute_children(children, rv) + { + for (var i=0; i<children.length; i++) + { + if (children[i] instanceof Object) { + var replacement = substitute(children[i], substitutions); + if (replacement !== null) + { + if (is_single_node(replacement)) + { + rv.push(replacement); + } + else + { + extend(rv, replacement); + } + } + } + else + { + extend(rv, do_substitution(String(children[i]))); + } + } + return rv; + } + + return rv; + } + + function make_dom_single(template) + { + if (template[0] === "{text}") + { + var element = document.createTextNode(""); + for (var i=1; i<template.length; i++) + { + element.data += template[i]; + } + } + else + { + var element = document.createElement(template[0]); + for (name in template[1]) { + if (template[1].hasOwnProperty(name)) + { + element.setAttribute(name, template[1][name]); + } + } + for (var i=2; i<template.length; i++) + { + if (template[i] instanceof Object) + { + var sub_element = make_dom(template[i]); + element.appendChild(sub_element); + } + else + { + var text_node = document.createTextNode(template[i]); + element.appendChild(text_node); + } + } + } + + return element; + } + + + + function make_dom(template, substitutions) + { + if (is_single_node(template)) + { + return make_dom_single(template); + } + else + { + return map(template, function(x) { + return make_dom_single(x); + }); + } + } + + function render(template, substitutions) + { + return make_dom(substitute(template, substitutions)); + } + expose(render, "template.render"); + +function expose(object, name) +{ + var components = name.split("."); + var target = window; + for (var i=0; i<components.length - 1; i++) + { + if (!(components[i] in target)) + { + target[components[i]] = {}; + } + target = target[components[i]]; + } + target[components[components.length - 1]] = object; +} + +function extend(array, items) +{ + Array.prototype.push.apply(array, items); +}
\ No newline at end of file |