template.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*!
  2. * template.js v0.7.1 (https://github.com/yanhaijing/template.js)
  3. * API https://github.com/yanhaijing/template.js/blob/master/doc/api.md
  4. * Copyright 2015 yanhaijing. All Rights Reserved
  5. * Licensed under MIT (https://github.com/yanhaijing/template.js/blob/master/MIT-LICENSE.txt)
  6. */
  7. ;(function(root, factory) {
  8. var template = factory(root);
  9. if (typeof define === 'function' && define.amd) {
  10. // AMD
  11. define('template', function() {
  12. return template;
  13. });
  14. } else if (typeof exports === 'object') {
  15. // Node.js
  16. module.exports = template;
  17. } else {
  18. // Browser globals
  19. var _template = root.template;
  20. template.noConflict = function() {
  21. if (root.template === template) {
  22. root.template = _template;
  23. }
  24. return template;
  25. };
  26. root.template = template;
  27. }
  28. }(this, function(root) {
  29. 'use strict';
  30. var o = {
  31. sTag: '<%',//开始标签
  32. eTag: '%>',//结束标签
  33. compress: false,//是否压缩html
  34. escape: true, //默认输出是否进行HTML转义
  35. error: function (e) {}//错误回调
  36. };
  37. var functionMap = {}; //内部函数对象
  38. //修饰器前缀
  39. var modifierMap = {
  40. '': function (param) {return nothing(param)},
  41. 'h': function (param) {return encodeHTML(param)},
  42. 'u': function (param) {return encodeURI(param)}
  43. };
  44. var toString = {}.toString;
  45. var slice = [].slice;
  46. function type(x) {
  47. if(x === null){
  48. return 'null';
  49. }
  50. var t= typeof x;
  51. if(t !== 'object'){
  52. return t;
  53. }
  54. var c = toString.call(x).slice(8, -1).toLowerCase();
  55. if(c !== 'object'){
  56. return c;
  57. }
  58. if(x.constructor==Object){
  59. return c;
  60. }
  61. return 'unkonw';
  62. }
  63. function isObject(obj) {
  64. return type(obj) === 'object';
  65. }
  66. function isFunction(fn) {
  67. return type(fn) === 'function';
  68. }
  69. function isString(str) {
  70. return type(str) === 'string';
  71. }
  72. function extend() {
  73. var target = arguments[0] || {};
  74. var arrs = slice.call(arguments, 1);
  75. var len = arrs.length;
  76. for (var i = 0; i < len; i++) {
  77. var arr = arrs[i];
  78. for (var name in arr) {
  79. target[name] = arr[name];
  80. }
  81. }
  82. return target;
  83. }
  84. function clone() {
  85. var args = slice.call(arguments);
  86. return extend.apply(null, [{}].concat(args));
  87. }
  88. function nothing(param) {
  89. return param;
  90. }
  91. function encodeHTML(source) {
  92. return String(source)
  93. .replace(/&/g,'&amp;')
  94. .replace(/</g,'&lt;')
  95. .replace(/>/g,'&gt;')
  96. .replace(/\\/g,'&#92;')
  97. .replace(/"/g,'&quot;')
  98. .replace(/'/g,'&#39;');
  99. }
  100. function compress(html) {
  101. return html.replace(/\s+/g, ' ').replace(/<!--[\w\W]*?-->/g, '');
  102. }
  103. function consoleAdapter(cmd, msg) {
  104. typeof console !== 'undefined' && console[cmd] && console[cmd](msg);
  105. }
  106. function handelError(e) {
  107. var message = 'template.js error\n\n';
  108. for (var key in e) {
  109. message += '<' + key + '>\n' + e[key] + '\n\n';
  110. }
  111. message += '<message>\n' + e.message + '\n\n';
  112. consoleAdapter('error', message);
  113. o.error(e);
  114. function error() {
  115. return 'template.js error';
  116. }
  117. error.toString = function () {
  118. return '__code__ = "template.js error"';
  119. }
  120. return error;
  121. }
  122. function parse(tpl, opt) {
  123. var code = '';
  124. var sTag = opt.sTag;
  125. var eTag = opt.eTag;
  126. var escape = opt.escape;
  127. function parsehtml(line) {
  128. // 单双引号转义,换行符替换为空格
  129. line = line.replace(/('|")/g, '\\$1').replace(/\n/g, ' ');
  130. return ';__code__ += ("' + line + '")\n';
  131. }
  132. function parsejs(line) {
  133. //var reg = /^(:?)(.*?)=(.*)$/;
  134. var reg = /^(?:=|(:.*?)=)(.*)$/
  135. var html;
  136. var arr;
  137. var modifier;
  138. // = := :*=
  139. // :h=123 [':h=123', 'h', '123']
  140. if (arr = reg.exec(line)) {
  141. html = arr[2]; // 输出
  142. if (Boolean(arr[1])) {
  143. // :开头
  144. modifier = arr[1].slice(1);
  145. } else {
  146. // = 开头
  147. modifier = escape ? 'h' : '';
  148. }
  149. return ';__code__ += __modifierMap__["' + modifier + '"](typeof (' + html + ') !== "undefined" ? (' + html + ') : "")\n';
  150. }
  151. //原生js
  152. return ';' + line + '\n';
  153. }
  154. var tokens = tpl.split(sTag);
  155. for (var i = 0, len = tokens.length; i < len; i++) {
  156. var token = tokens[i].split(eTag);
  157. if (token.length === 1) {
  158. code += parsehtml(token[0]);
  159. } else {
  160. code += parsejs(token[0], true);
  161. if (token[1]) {
  162. code += parsehtml(token[1]);
  163. }
  164. }
  165. }
  166. return code;
  167. }
  168. function compiler(tpl, opt) {
  169. var mainCode = parse(tpl, opt);
  170. var headerCode = '\n' +
  171. ' var html = (function (__data__, __modifierMap__) {\n' +
  172. ' var __str__ = "", __code__ = "";\n' +
  173. ' for(var key in __data__) {\n' +
  174. ' __str__+=("var " + key + "=__data__[\'" + key + "\'];");\n' +
  175. ' }\n' +
  176. ' eval(__str__);\n\n';
  177. var footerCode = '\n' +
  178. ' ;return __code__;\n' +
  179. ' }(__data__, __modifierMap__));\n' +
  180. ' return html;\n';
  181. var code = headerCode + mainCode + footerCode;
  182. code = code.replace(/[\r]/g, ' '); // ie 7 8 会报错,不知道为什么
  183. try {
  184. var Render = new Function('__data__', '__modifierMap__', code);
  185. Render.toString = function () {
  186. return mainCode;
  187. }
  188. return Render;
  189. } catch(e) {
  190. e.temp = 'function anonymous(__data__, __modifierMap__) {' + code + '}';
  191. throw e;
  192. }
  193. }
  194. function compile(tpl, opt) {
  195. opt = clone(o, opt);
  196. try {
  197. var Render = compiler(tpl, opt);
  198. } catch(e) {
  199. e.name = 'CompileError';
  200. e.tpl = tpl;
  201. e.render = e.temp;
  202. delete e.temp;
  203. return handelError(e);
  204. }
  205. function render(data) {
  206. data = clone(functionMap, data);
  207. try {
  208. var html = Render(data, modifierMap);
  209. html = opt.compress ? compress(html) : html;
  210. return html;
  211. } catch(e) {
  212. e.name = 'RenderError';
  213. e.tpl = tpl;
  214. e.render = Render.toString();
  215. return handelError(e)();
  216. }
  217. }
  218. render.toString = function () {
  219. return Render.toString();
  220. };
  221. return render;
  222. }
  223. function template(tpl, data) {
  224. if (typeof tpl !== 'string') {
  225. return '';
  226. }
  227. var fn = compile(tpl);
  228. if (!isObject(data)) {
  229. return fn;
  230. }
  231. return fn(data);
  232. }
  233. template.config = function (option) {
  234. if (isObject(option)) {
  235. o = extend(o, option);
  236. }
  237. return clone(o);
  238. };
  239. template.registerFunction = function(name, fn) {
  240. if (!isString(name)) {
  241. return clone(functionMap);
  242. }
  243. if (!isFunction(fn)) {
  244. return functionMap[name];
  245. }
  246. return functionMap[name] = fn;
  247. }
  248. template.unregisterFunction = function (name) {
  249. if (!isString(name)) {
  250. return false;
  251. }
  252. delete functionMap[name];
  253. return true;
  254. }
  255. template.registerModifier = function(name, fn) {
  256. if (!isString(name)) {
  257. return clone(modifierMap);
  258. }
  259. if (!isFunction(fn)) {
  260. return modifierMap[name];
  261. }
  262. return modifierMap[name] = fn;
  263. }
  264. template.unregisterModifier = function (name) {
  265. if (!isString(name)) {
  266. return false;
  267. }
  268. delete modifierMap[name];
  269. return true;
  270. }
  271. template.__encodeHTML = encodeHTML;
  272. template.__compress = compress;
  273. template.__handelError = handelError;
  274. template.__compile = compile;
  275. template.version = '0.7.1';
  276. return template;
  277. }));