PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/yuilib/3.9.1/build/template-micro/template-micro-debug.js

https://bitbucket.org/kudutest/moodlegit
JavaScript | 250 lines | 62 code | 27 blank | 161 comment | 4 complexity | ec335b3492370479debd9f51bf2d51ef MD5 | raw file
  1. /* YUI 3.9.1 (build 5852) Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
  2. YUI.add('template-micro', function (Y, NAME) {
  3. /*jshint expr:true */
  4. /**
  5. Adds the `Y.Template.Micro` template engine, which provides fast, simple
  6. string-based micro-templating similar to ERB or Underscore templates.
  7. @module template
  8. @submodule template-micro
  9. @since 3.8.0
  10. **/
  11. /**
  12. Fast, simple string-based micro-templating engine similar to ERB or Underscore
  13. templates.
  14. @class Template.Micro
  15. @static
  16. @since 3.8.0
  17. **/
  18. // This code was heavily inspired by Underscore.js's _.template() method
  19. // (written by Jeremy Ashkenas), which was in turn inspired by John Resig's
  20. // micro-templating implementation.
  21. var Micro = Y.namespace('Template.Micro');
  22. /**
  23. Default options for `Y.Template.Micro`.
  24. @property {Object} options
  25. @param {RegExp} [options.code] Regex that matches code blocks like
  26. `<% ... %>`.
  27. @param {RegExp} [options.escapedOutput] Regex that matches escaped output
  28. tags like `<%= ... %>`.
  29. @param {RegExp} [options.rawOutput] Regex that matches raw output tags like
  30. `<%== ... %>`.
  31. @param {RegExp} [options.stringEscape] Regex that matches characters that
  32. need to be escaped inside single-quoted JavaScript string literals.
  33. @param {Object} [options.stringReplace] Hash that maps characters matched by
  34. `stringEscape` to the strings they should be replaced with. If you add
  35. a character to the `stringEscape` regex, you need to add it here too or
  36. it will be replaced with an empty string.
  37. @static
  38. @since 3.8.0
  39. **/
  40. Micro.options = {
  41. code : /<%([\s\S]+?)%>/g,
  42. escapedOutput: /<%=([\s\S]+?)%>/g,
  43. rawOutput : /<%==([\s\S]+?)%>/g,
  44. stringEscape : /\\|'|\r|\n|\t|\u2028|\u2029/g,
  45. stringReplace: {
  46. '\\' : '\\\\',
  47. "'" : "\\'",
  48. '\r' : '\\r',
  49. '\n' : '\\n',
  50. '\t' : '\\t',
  51. '\u2028': '\\u2028',
  52. '\u2029': '\\u2029'
  53. }
  54. };
  55. /**
  56. Compiles a template string into a JavaScript function. Pass a data object to the
  57. function to render the template using the given data and get back a rendered
  58. string.
  59. Within a template, use `<%= ... %>` to output the value of an expression (where
  60. `...` is the JavaScript expression or data variable to evaluate). The output
  61. will be HTML-escaped by default. To output a raw value without escaping, use
  62. `<%== ... %>`, but be careful not to do this with untrusted user input.
  63. To execute arbitrary JavaScript code within the template without rendering its
  64. output, use `<% ... %>`, where `...` is the code to be executed. This allows the
  65. use of if/else blocks, loops, function calls, etc., although it's recommended
  66. that you avoid embedding anything beyond basic flow control logic in your
  67. templates.
  68. Properties of the data object passed to a template function are made available
  69. on a `data` variable within the scope of the template. So, if you pass in
  70. the object `{message: 'hello!'}`, you can print the value of the `message`
  71. property using `<%= data.message %>`.
  72. @example
  73. YUI().use('template-micro', function (Y) {
  74. var template = '<ul class="<%= data.classNames.list %>">' +
  75. '<% Y.Array.each(data.items, function (item) { %>' +
  76. '<li><%= item %></li>' +
  77. '<% }); %>' +
  78. '</ul>';
  79. // Compile the template into a function.
  80. var compiled = Y.Template.Micro.compile(template);
  81. // Render the template to HTML, passing in the data to use.
  82. var html = compiled({
  83. classNames: {list: 'demo'},
  84. items : ['one', 'two', 'three', 'four']
  85. });
  86. });
  87. @method compile
  88. @param {String} text Template text to compile.
  89. @param {Object} [options] Options. If specified, these options will override the
  90. default options defined in `Y.Template.Micro.options`. See the documentation
  91. for that property for details on which options are available.
  92. @return {Function} Compiled template function. Execute this function and pass in
  93. a data object to render the template with the given data.
  94. @static
  95. @since 3.8.0
  96. **/
  97. Micro.compile = function (text, options) {
  98. /*jshint evil:true */
  99. var blocks = [],
  100. tokenClose = "\uffff",
  101. tokenOpen = "\ufffe",
  102. source;
  103. options = Y.merge(Micro.options, options);
  104. // Parse the input text into a string of JavaScript code, with placeholders
  105. // for code blocks. Text outside of code blocks will be escaped for safe
  106. // usage within a double-quoted string literal.
  107. //
  108. // $b is a blank string, used to avoid creating lots of string objects.
  109. //
  110. // $v is a function that returns the supplied value if the value is truthy
  111. // or the number 0, or returns an empty string if the value is falsy and not
  112. // 0.
  113. //
  114. // $t is the template string.
  115. source = "var $b='', $v=function (v){return v || v === 0 ? v : $b;}, $t='" +
  116. // U+FFFE and U+FFFF are guaranteed to represent non-characters, so no
  117. // valid UTF-8 string should ever contain them. That means we can freely
  118. // strip them out of the input text (just to be safe) and then use them
  119. // for our own nefarious purposes as token placeholders!
  120. //
  121. // See http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Noncharacters
  122. text.replace(/\ufffe|\uffff/g, '')
  123. .replace(options.rawOutput, function (match, code) {
  124. return tokenOpen + (blocks.push("'+\n$v(" + code + ")+\n'") - 1) + tokenClose;
  125. })
  126. .replace(options.escapedOutput, function (match, code) {
  127. return tokenOpen + (blocks.push("'+\n$e($v(" + code + "))+\n'") - 1) + tokenClose;
  128. })
  129. .replace(options.code, function (match, code) {
  130. return tokenOpen + (blocks.push("';\n" + code + "\n$t+='") - 1) + tokenClose;
  131. })
  132. .replace(options.stringEscape, function (match) {
  133. return options.stringReplace[match] || '';
  134. })
  135. // Replace the token placeholders with code.
  136. .replace(/\ufffe(\d+)\uffff/g, function (match, index) {
  137. return blocks[parseInt(index, 10)];
  138. })
  139. // Remove noop string concatenations that have been left behind.
  140. .replace(/\n\$t\+='';\n/g, '\n') +
  141. "';\nreturn $t;";
  142. // If compile() was called from precompile(), return precompiled source.
  143. if (options.precompile) {
  144. return "function (Y, $e, data) {\n" + source + "\n}";
  145. }
  146. // Otherwise, return an executable function.
  147. return this.revive(new Function('Y', '$e', 'data', source));
  148. };
  149. /**
  150. Precompiles the given template text into a string of JavaScript source code that
  151. can be evaluated later in another context (or on another machine) to render the
  152. template.
  153. A common use case is to precompile templates at build time or on the server,
  154. then evaluate the code on the client to render a template. The client only needs
  155. to revive and render the template, avoiding the work of the compilation step.
  156. @method precompile
  157. @param {String} text Template text to precompile.
  158. @param {Object} [options] Options. If specified, these options will override the
  159. default options defined in `Y.Template.Micro.options`. See the documentation
  160. for that property for details on which options are available.
  161. @return {String} Source code for the precompiled template.
  162. @static
  163. @since 3.8.0
  164. **/
  165. Micro.precompile = function (text, options) {
  166. options || (options = {});
  167. options.precompile = true;
  168. return this.compile(text, options);
  169. };
  170. /**
  171. Compiles and renders the given template text in a single step.
  172. This can be useful for single-use templates, but if you plan to render the same
  173. template multiple times, it's much better to use `compile()` to compile it once,
  174. then simply call the compiled function multiple times to avoid recompiling.
  175. @method render
  176. @param {String} text Template text to render.
  177. @param {Object} data Data to pass to the template.
  178. @param {Object} [options] Options. If specified, these options will override the
  179. default options defined in `Y.Template.Micro.options`. See the documentation
  180. for that property for details on which options are available.
  181. @return {String} Rendered result.
  182. @static
  183. @since 3.8.0
  184. **/
  185. Micro.render = function (text, data, options) {
  186. return this.compile(text, options)(data);
  187. };
  188. /**
  189. Revives a precompiled template function into a normal compiled template function
  190. that can be called to render the template. The precompiled function must already
  191. have been evaluated to a function -- you can't pass raw JavaScript code to
  192. `revive()`.
  193. @method revive
  194. @param {Function} precompiled Precompiled template function.
  195. @return {Function} Revived template function, ready to be rendered.
  196. @static
  197. @since 3.8.0
  198. **/
  199. Micro.revive = function (precompiled) {
  200. return function (data) {
  201. data || (data = {});
  202. return precompiled.call(data, Y, Y.Escape.html, data);
  203. };
  204. };
  205. }, '3.9.1', {"requires": ["escape"]});