Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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