Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

133 строки
3.2KB

  1. /*
  2. Shamless port of http://github.com/defunkt/mustache
  3. by Jan Lehnardt <jan@apache.org>
  4. Thanks @defunkt for the awesome code
  5. TBD: MIT, see LICENSE
  6. ChangeLog:
  7. - 04.10.2009: Ininitial port at http://devhouseberlin.de/
  8. */
  9. var Mustache = {
  10. name: "mustache.js",
  11. version: "0.1",
  12. debug: true,
  13. stack: " ",
  14. context: {},
  15. to_html: function(template, view) {
  16. return this.render(template, view);
  17. },
  18. render: function(template, view) {
  19. this.stack = this.stack + " ";
  20. // fail fast
  21. if(template.indexOf("{{") == -1) {
  22. return template;
  23. }
  24. this.context = context = this.merge((this.context || {}), view);
  25. var html = this.render_section(template);
  26. // restore context, recursion might have messed it up
  27. this.context = context;
  28. return this.render_tags(html);
  29. },
  30. render_partial: function(name) {
  31. var evil_name = eval(name)
  32. switch(typeof evil_name) {
  33. case "string":
  34. return this.to_html(evil_name, "");
  35. case "object":
  36. var tpl = name + "_template";
  37. return this.to_html(eval(tpl), evil_name);
  38. default:
  39. throw("Unknown partial type.");
  40. }
  41. },
  42. merge: function(a, b) {
  43. for(var name in b) {
  44. if(b.hasOwnProperty(name)) {
  45. a[name] = b[name];
  46. }
  47. }
  48. return a;
  49. },
  50. render_section: function(template) {
  51. if(template.indexOf("{{#") == -1) {
  52. return template;
  53. }
  54. var that = this;
  55. return template.replace(/\{\{\#(.+)\}\}\s*([\s\S]+)\{\{\/\1\}\}\s*/mg,
  56. function(match, name, content) {
  57. var value = that.find(name);
  58. if(that.is_array(value)) {
  59. return value.map(function(row) {
  60. return that.render(content, row);
  61. }).join('');
  62. } else if(value) {
  63. return that.render(content);
  64. } else {
  65. return "";
  66. }
  67. }
  68. );
  69. },
  70. is_array: function(a) {
  71. return (a &&
  72. typeof a === 'object' &&
  73. a.constructor === Array);
  74. },
  75. render_tags: function(template) {
  76. // values
  77. var that = this;
  78. return template.replace(/\{\{(!|<|\{)?([^\/#]+?)\1?\}\}+/mg,
  79. function (match, operator, name) {
  80. switch(operator) {
  81. case "!": // ignore comments
  82. return match;
  83. case "<": // render partial
  84. return that.render_partial(name);
  85. case '{': // the triple mustache is unescaped
  86. return that.find(name);
  87. default: // escape the value
  88. return that.escape(that.find(name));
  89. }
  90. }, this);
  91. },
  92. escape: function(s) {
  93. return s.toString().replace(/[&"<>\\]/g, function(s) {
  94. switch(s) {
  95. case "&": return "&amp;";
  96. case "\\": return "\\\\";;
  97. case '"': return '\"';;
  98. case "<": return "&lt;";
  99. case ">": return "&gt;";
  100. default: return s;
  101. }
  102. });
  103. },
  104. find: function(name) {
  105. name = this.trim(name);
  106. // print(this.stack + "find(" + name + ")");
  107. var context = this.context;
  108. if(typeof context[name] === "function") {
  109. return context[name].apply(context);
  110. }
  111. if(context[name] !== undefined) {
  112. return context[name];
  113. }
  114. throw("Can't find " + name + " in " + context);
  115. },
  116. trim: function(s) {
  117. return s.replace(/^\s*|\s*$/g, '');
  118. },
  119. };