Quellcode durchsuchen

nice comments

tags/0.2
Jan Lehnardt vor 16 Jahren
Ursprung
Commit
09e6613d93
1 geänderte Dateien mit 78 neuen und 35 gelöschten Zeilen
  1. +78
    -35
      mustache.js

+ 78
- 35
mustache.js Datei anzeigen

@@ -2,67 +2,77 @@
Shamless port of http://github.com/defunkt/mustache Shamless port of http://github.com/defunkt/mustache
by Jan Lehnardt <jan@apache.org> by Jan Lehnardt <jan@apache.org>


Thanks @defunkt for the awesome code
Thanks @defunkt for the awesome code.
See http://github.com/defunkt/mustache for more info.
*/ */


var Mustache = { var Mustache = {
name: "mustache.js", name: "mustache.js",
version: "0.1", version: "0.1",
debug: true,
stack: " ",
context: {}, context: {},

/*
Public method. Turns a template and view into HTML
*/
to_html: function(template, view) { to_html: function(template, view) {
return this.render(template, view); return this.render(template, view);
}, },


// Private Methods
render: function(template, view) { render: function(template, view) {
this.stack = this.stack + " ";
// fail fast // fail fast
if(template.indexOf("{{") == -1) { if(template.indexOf("{{") == -1) {
return template; return template;
} }

// keep context around for recursive calls
this.context = context = this.merge((this.context || {}), view); this.context = context = this.merge((this.context || {}), view);

// first, render all sections
var html = this.render_section(template); var html = this.render_section(template);

// restore context, recursion might have messed it up // restore context, recursion might have messed it up
this.context = context; this.context = context;
// finally, render tags
return this.render_tags(html); return this.render_tags(html);
}, },


/*
Tries to find a partial in the global scope and render it
*/
render_partial: function(name) { render_partial: function(name) {
// FIXME: too hacky
var evil_name = eval(name) var evil_name = eval(name)
switch(typeof evil_name) { switch(typeof evil_name) {
case "string":
case "string": // a tring partial, we simply render
return this.to_html(evil_name, ""); return this.to_html(evil_name, "");
case "object":
case "object": // a view partial needs a `name_template` template to render
var tpl = name + "_template"; var tpl = name + "_template";
return this.to_html(eval(tpl), evil_name); return this.to_html(eval(tpl), evil_name);
default:
default: // should not happen #famouslastwords
throw("Unknown partial type."); throw("Unknown partial type.");
} }
}, },


merge: function(a, b) {
for(var name in b) {
if(b.hasOwnProperty(name)) {
a[name] = b[name];
}
}
return a;
},

/*
Renders boolean and enumerable sections
*/
render_section: function(template) { render_section: function(template) {
if(template.indexOf("{{#") == -1) { if(template.indexOf("{{#") == -1) {
return template; return template;
} }
var that = this; var that = this;
// for each {{#foo}}{{/foo}} section do...
return template.replace(/\{\{\#(.+)\}\}\s*([\s\S]+)\{\{\/\1\}\}\s*/mg, return template.replace(/\{\{\#(.+)\}\}\s*([\s\S]+)\{\{\/\1\}\}\s*/mg,
function(match, name, content) { function(match, name, content) {
var value = that.find(name); var value = that.find(name);
if(that.is_array(value)) {
if(that.is_array(value)) { // Enumerable, Let's loop!
return value.map(function(row) { return value.map(function(row) {
return that.render(content, row); return that.render(content, row);
}).join(''); }).join('');
} else if(value) {
} else if(value) { // boolean section
return that.render(content); return that.render(content);
} else { } else {
return ""; return "";
@@ -71,15 +81,13 @@ var Mustache = {
); );
}, },


is_array: function(a) {
return (a &&
typeof a === 'object' &&
a.constructor === Array);
},

/*
Replace {{foo}} and friends with values from our view
*/
render_tags: function(template) { render_tags: function(template) {
// values
// tit for tat
var that = this; var that = this;
// for each {{(!<{)?foo}} tag, do...
return template.replace(/\{\{(!|<|\{)?([^\/#]+?)\1?\}\}+/mg, return template.replace(/\{\{(!|<|\{)?([^\/#]+?)\1?\}\}+/mg,
function (match, operator, name) { function (match, operator, name) {
switch(operator) { switch(operator) {
@@ -95,6 +103,27 @@ var Mustache = {
}, this); }, this);
}, },
/*
find `name` in current `context`. That is find me a value
from the view object
*/
find: function(name) {
name = this.trim(name);
var context = this.context;
if(typeof context[name] === "function") {
return context[name].apply(context);
}
if(context[name] !== undefined) {
return context[name];
}
throw("Can't find " + name + " in " + context);
},

// Utility methods

/*
Does away with nasty characters
*/
escape: function(s) { escape: function(s) {
return s.toString().replace(/[&"<>\\]/g, function(s) { return s.toString().replace(/[&"<>\\]/g, function(s) {
switch(s) { switch(s) {
@@ -108,19 +137,33 @@ var Mustache = {
}); });
}, },


find: function(name) {
name = this.trim(name);
// print(this.stack + "find(" + name + ")");
var context = this.context;
if(typeof context[name] === "function") {
return context[name].apply(context);
}
if(context[name] !== undefined) {
return context[name];
/*
Merges all properties of object `b` into object `a`.
`b.property` overwrites a.property`
*/
merge: function(a, b) {
for(var name in b) {
if(b.hasOwnProperty(name)) {
a[name] = b[name];
}
} }
throw("Can't find " + name + " in " + context);
return a;
},

/*
Thanks Doug Crockford
JavaScript — The Good Parts lists an alternative that works better with
frames. Frames can suck it, we use the simple version.
*/
is_array: function(a) {
return (a &&
typeof a === 'object' &&
a.constructor === Array);
}, },


/*
Gets rid of leading and trailing whitespace
*/
trim: function(s) { trim: function(s) {
return s.replace(/^\s*|\s*$/g, ''); return s.replace(/^\s*|\s*$/g, '');
}, },


Laden…
Abbrechen
Speichern