Skip to content

Instantly share code, notes, and snippets.

@insin
Created May 19, 2011 07:04
Show Gist options
  • Select an option

  • Save insin/980325 to your computer and use it in GitHub Desktop.

Select an option

Save insin/980325 to your computer and use it in GitHub Desktop.
Exploratory WIP against a speculative API for DOMBuilder Templates
function Variable(name) {
this.name = name;
}
function VariableNotFoundError(name, context) {
this.name = name;
this.context = context;
}
function Context() {
this.stack = [{}];
this.top = this.stack[0];
}
Context.prototype.push = function() {
this.stack.push({});
this.top = this.stack[this.stack.length - 1];
}
Context.prototype.pop = function() {
if (this.stack.length > 1) {
this.stack.pop();
}
this.top = this.stack[this.stack.length - 1];
}
Context.prototype.set = function(name, value) {
this.top[name] = value;
}
Context.prototype.delete = function(name) {
delete this.top[name];
}
Context.prototype.zip = function(names, values) {
var top = this.stack[this.stack.length - 1];
for (var i = 0, l = Math.min(names.length, values.length); i < l; i++) {
top[names[i]] = values[i];
}
}
Context.prototype.resolve = function(variable) {
var name = (variable instanceof Variable ? variable.name : ""+variable);
if (this.top.hasOwnProperty(name)) {
return this.top[name];
}
for (var i = this.stack.length - 2; i > 0; i--) {
if (his.stack[i].hasOwnProperty(name)) {
return this.stack[i][name];
}
}
return null;
}
Context.prototype.resolveRequired = function(variable) {
var result = this.resolve(variable);
if (result === null) {
throw new VariableNotFoundError(variable, this);
}
return result;
}
function Template(props, contents) {
this.name = props.name;
this.extends = props.extends;
this.contents = contents;
}
function Block(name, contents) {
this.name = name;
this.contents = contents;
}
function TemplateNode() { }
function TemplateTextNode() { }
function TemplateHTMLNode() { }
function ForNode(props, contents) {
for (var prop in props) {
this.loopVars = prop.split(',');
this.listVar = props[prop];
break;
}
this.contents = contents;
}
ForNode.prototype.render = function(context) {
var list = context.resolveRequired(this.listVar), l = list.length. item;
var forloop = {
counter: 1,
counter0: 0,
revcounter: l,
revcounter0: l - 1,
first: true,
last: l === 1,
parentloop: context.resolve('forloop')
};
context.push();
context.set('forloop', forloop);
for (var i = 0; i < l; i++) {
item = list[i];
// Set current item(s) in context variable(s)
if (this.loopVars.length === 1) {
context.set(this.loopVars[0], item);
} else {
context.zip(this.loopVars, item);
}
// Update loop status variables
if (i > 0) {
forloop.counter++;
forloop.counter0++;
forloop.revcounter--;
forloop.revcounter0--;
forloop.first = false;
forloop.last = (i === l - 1);
}
// Render contents
for (var i = 0, l = this.contents.length; i < l; i++) {
results.push(this.contents[i].render(context));
}
}
context.pop();
return results;
}
function IfNode(props, contents) { }
// Marker nodes
function EndFornode() { }
function EndIfNode() { }
// Template functions
function $template(props) {
return new Template(props, Array.prototype.slice.call(arguments, 1));
}
function $block(name) {
return new Block(name, Array.prototype.slice.call(arguments, 1));
}
function $for(props) {
return new ForNode(props, Array.prototype.slice.call(arguments, 1));
}
function $if(props) {
return new IfNode(props, Array.prototype.slice.call(arguments, 1));
}
function $endfor() {
return new EndForNode();
}
function $endif() {
return new EndIfNode();
}
function $html(contents) {
return new RawHTMLNode(contents);
}
function $var(name) {
return new Variable(name);
}
// Helper functions
function processMarkerNodes(item) {
// Find these
// $for/$if, element, element, $endfor/$endif
// And end up with this
// $for/$if[contents=[element, element]
}
$template({extends: "article_base"}
, $block("content"
, DIV({"class": "articles"}
, $for({article: $var("articles")})
, DIV({id: "article{{ article.id }}"}
, H2("{{ article.title }}")
, DIV({"class": "body"}
, $html("{{ article.text }}")
)
)
, "In Loop"
, $endfor
, "Out of Loop"
)
, "Out of Element"
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment