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