123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- var Mustache = function() {
- var Renderer = function() {};
- Renderer.prototype = {
- otag: "{{",
- ctag: "}}",
- pragmas: {},
- buffer: [],
- pragmas_implemented: {
- "IMPLICIT-ITERATOR": true
- },
- context: {},
- render: function(template, context, partials, in_recursion) {
-
- if(!in_recursion) {
- this.context = context;
- this.buffer = [];
- }
-
- if(!this.includes("", template)) {
- if(in_recursion) {
- return template;
- } else {
- this.send(template);
- return;
- }
- }
- template = this.render_pragmas(template);
- var html = this.render_section(template, context, partials);
- if(in_recursion) {
- return this.render_tags(html, context, partials, in_recursion);
- }
- this.render_tags(html, context, partials, in_recursion);
- },
-
- send: function(line) {
- if(line != "") {
- this.buffer.push(line);
- }
- },
-
- render_pragmas: function(template) {
-
- if(!this.includes("%", template)) {
- return template;
- }
- var that = this;
- var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
- this.ctag);
- return template.replace(regex, function(match, pragma, options) {
- if(!that.pragmas_implemented[pragma]) {
- throw({message:
- "This implementation of mustache doesn't understand the '" +
- pragma + "' pragma"});
- }
- that.pragmas[pragma] = {};
- if(options) {
- var opts = options.split("=");
- that.pragmas[pragma][opts[0]] = opts[1];
- }
- return "";
-
- });
- },
-
- render_partial: function(name, context, partials) {
- name = this.trim(name);
- if(!partials || partials[name] === undefined) {
- throw({message: "unknown_partial '" + name + "'"});
- }
- if(typeof(context[name]) != "object") {
- return this.render(partials[name], context, partials, true);
- }
- return this.render(partials[name], context[name], partials, true);
- },
-
- render_section: function(template, context, partials) {
- if(!this.includes("#", template) && !this.includes("^", template)) {
- return template;
- }
- var that = this;
-
- var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
- "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
- "\\s*", "mg");
-
- return template.replace(regex, function(match, type, name, content) {
- var value = that.find(name, context);
- if(type == "^") {
- if(!value || that.is_array(value) && value.length === 0) {
-
- return that.render(content, context, partials, true);
- } else {
- return "";
- }
- } else if(type == "#") {
- if(that.is_array(value)) {
- return that.map(value, function(row) {
- return that.render(content, that.create_context(row),
- partials, true);
- }).join("");
- } else if(that.is_object(value)) {
- return that.render(content, that.create_context(value),
- partials, true);
- } else if(typeof value === "function") {
-
- return value.call(context, content, function(text) {
- return that.render(text, context, partials, true);
- });
- } else if(value) {
- return that.render(content, context, partials, true);
- } else {
- return "";
- }
- }
- });
- },
-
- render_tags: function(template, context, partials, in_recursion) {
-
- var that = this;
- var new_regex = function() {
- return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
- that.ctag + "+", "g");
- };
- var regex = new_regex();
- var tag_replace_callback = function(match, operator, name) {
- switch(operator) {
- case "!":
- return "";
- case "=":
- that.set_delimiters(name);
- regex = new_regex();
- return "";
- case ">":
- return that.render_partial(name, context, partials);
- case "{":
- return that.find(name, context);
- default:
- return that.escape(that.find(name, context));
- }
- };
- var lines = template.split("\n");
- for(var i = 0; i < lines.length; i++) {
- lines[i] = lines[i].replace(regex, tag_replace_callback, this);
- if(!in_recursion) {
- this.send(lines[i]);
- }
- }
- if(in_recursion) {
- return lines.join("\n");
- }
- },
- set_delimiters: function(delimiters) {
- var dels = delimiters.split(" ");
- this.otag = this.escape_regex(dels[0]);
- this.ctag = this.escape_regex(dels[1]);
- },
- escape_regex: function(text) {
-
- if(!arguments.callee.sRE) {
- var specials = [
- '/', '.', '*', '+', '?', '|',
- '(', ')', '[', ']', '{', '}', '\\'
- ];
- arguments.callee.sRE = new RegExp(
- '(\\' + specials.join('|\\') + ')', 'g'
- );
- }
- return text.replace(arguments.callee.sRE, '\\$1');
- },
-
- find: function(name, context) {
- name = this.trim(name);
-
- function is_kinda_truthy(bool) {
- return bool === false || bool === 0 || bool;
- }
- var value;
- if(is_kinda_truthy(context[name])) {
- value = context[name];
- } else if(is_kinda_truthy(this.context[name])) {
- value = this.context[name];
- }
- if(typeof value === "function") {
- return value.apply(context);
- }
- if(value !== undefined) {
- return value;
- }
-
- return "";
- },
-
-
- includes: function(needle, haystack) {
- return haystack.indexOf(this.otag + needle) != -1;
- },
-
- escape: function(s) {
- s = String(s === null ? "" : s);
- return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
- switch(s) {
- case "&": return "&";
- case "\\": return "\\\\";
- case '"': return '"';
- case "'": return ''';
- case "<": return "<";
- case ">": return ">";
- default: return s;
- }
- });
- },
-
- create_context: function(_context) {
- if(this.is_object(_context)) {
- return _context;
- } else {
- var iterator = ".";
- if(this.pragmas["IMPLICIT-ITERATOR"]) {
- iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
- }
- var ctx = {};
- ctx[iterator] = _context;
- return ctx;
- }
- },
- is_object: function(a) {
- return a && typeof a == "object";
- },
- is_array: function(a) {
- return Object.prototype.toString.call(a) === '[object Array]';
- },
-
- trim: function(s) {
- return s.replace(/^\s*|\s*$/g, "");
- },
-
- map: function(array, fn) {
- if (typeof array.map == "function") {
- return array.map(fn);
- } else {
- var r = [];
- var l = array.length;
- for(var i = 0; i < l; i++) {
- r.push(fn(array[i]));
- }
- return r;
- }
- }
- };
- return({
- name: "mustache.js",
- version: "0.3.1-dev",
-
- to_html: function(template, view, partials, send_fun) {
- var renderer = new Renderer();
- if(send_fun) {
- renderer.send = send_fun;
- }
- renderer.render(template, view, partials);
- if(!send_fun) {
- return renderer.buffer.join("\n");
- }
- }
- });
- }();
|