Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('loader-pathogen-combohandler', function (Y, NAME) {
2
 
3
/*jslint vars: true */
4
var GROUP_DELIM = ';',
5
    SUB_GROUP_DELIM = '+',
6
    MODULE_DELIM = ',',
7
    FILTER_RE = /-(min|debug).js/,
8
    EXTENSION_RE = /\.(?:js|css)$/,
9
    galleryVersion,
10
    GALLERY_RE = /^(?:yui:)?gallery-([^\/]+)/,
11
    TYPES = { js: true, css: true },
12
    customComboBase;
13
 
14
Y.mix(Y.Loader.prototype, {
15
    /**
16
     * Encodes combo urls based on modules  and appends them to an object hash of arrays from `loader.resolve`.
17
     *
18
     * @method _pathogenEncodeComboSources
19
     * @param {Object} resolved The object hash of arrays in which to attach the encoded combo sources.
20
     * @return Object
21
     * @private
22
     */
23
    _pathogenEncodeComboSources: function (resolved) {
24
        var combine = this.combine,
25
            resolvedUrls,
26
            maxURLLength,
27
            resolvedMods,
28
            comboUrls,
29
            urlKey,
30
            modKey,
31
            group,
32
            type;
33
 
34
        // Check to see if anything needs to be combined.
35
        if (!combine) {
36
            for (group in this.groups) {
37
                if (this.groups.hasOwnProperty(group)) {
38
                    if (!combine && group.combine) {
39
                        combine = group.combine;
40
                        break;
41
                    }
42
                }
43
            }
44
        }
45
 
46
        // Add the pathogen namespace to the combo base.
47
        if (Y.config.customComboBase) {
48
            customComboBase = Y.config.customComboBase;
49
        }
50
 
51
        if (customComboBase && combine) {
52
            maxURLLength = this.maxURLLength;
53
 
54
            for (type in TYPES) {
55
                /*jslint forin: false*/
56
                if (!TYPES.hasOwnProperty(type)) {
57
                /*jslint forin: true*/
58
                    continue;
59
                }
60
 
61
                urlKey  = type;
62
                modKey  = type + 'Mods';
63
 
64
                resolved[urlKey] = resolvedUrls = resolved[urlKey] || [];
65
                resolved[modKey] = resolvedMods = resolved[modKey] || [];
66
 
67
                // Generate custom combo urls.
68
                comboUrls = this._customResolve(resolvedMods, type);
69
 
70
                Y.log('Default encoding resulted in ' + resolved[type].length + ' URLs', 'info', NAME);
71
                Y.log(Y.dump(resolved[type]), 'info', NAME);
72
                Y.log('Custom encoding resulted in ' + comboUrls.length + ' URLs', 'info', NAME);
73
                Y.log(Y.dump(comboUrls), 'info', NAME);
74
 
75
                resolved[type] = resolved[type].concat(comboUrls);
76
            }
77
        }
78
 
79
        return resolved;
80
    },
81
 
82
    /**
83
    Build each combo url from the bottom up. There's probably room for optimization
84
    here, but let's keep it simple for now.
85
    @method _customResolve
86
    @param {Array} modules A list of module meta.
87
    @param {String} type Either `js` or `css`.
88
    @return {String} Combo url.
89
    @private
90
    */
91
    _customResolve: function (modules, type) {
92
        var source = this._aggregateGroups(modules),
93
            groups = this._sortAggregatedGroups(source),
94
            comboUrls = [],
95
            comboTail,
96
            filter,
97
            match,
98
            url;
99
 
100
        // Determine the combo tail (e.g., '.debug.js'). Assumption: `filter` is
101
        // global to the resolve() and should match the filter on loader.
102
        if (!filter) {
103
            match = FILTER_RE.exec(Y.config.loaderPath);
104
            filter = match && match[1] || 'raw';
105
            filter = (type === 'css' && filter === 'debug') ? 'raw' : 'min';
106
            comboTail = filter === 'min' ? '' : '.' + filter;
107
            comboTail = comboTail + '.' + type;
108
        }
109
 
110
        url = this._buildCombo(groups, customComboBase, comboTail);
111
        while (url) {
112
            comboUrls.push(url);
113
            url = this._buildCombo(groups, customComboBase, comboTail);
114
        }
115
 
116
        return comboUrls;
117
    },
118
 
119
    /**
120
    Aggregate modules into groups with unique keys. The key is "$name+$version" for
121
    core and gallery groups, and just "$root" for all other groups.
122
    @method _aggregateGroups
123
    @param {Array} modules A list of module meta.
124
    @return {Object} Aggregated groups of module meta.
125
    @private
126
    */
127
    _aggregateGroups: function (modules) {
128
        var source = {},
129
            galleryMatch,
130
            meta,
131
            name,
132
            mod,
133
            key,
134
            len,
135
            i;
136
 
137
        // Segment the modules for efficient combo encoding.
138
        for (i = 0, len = modules.length; i < len; i += 1) {
139
            mod     = modules[i];
140
            name    = mod.name;
141
 
142
            // Skip modules that should be loaded singly. This is kind of confusing
143
            // because it mimics the behavior of the loader (also confusing):
144
            // https://github.com/ekashida/yui3/blob/632167a36d57da7a884aacf0f4488dd5b8619c7c/src/loader/js/loader.js#L2563
145
            meta = this.groups && this.groups[mod.group];
146
            if (meta) {
147
                if (!meta.combine || mod.fullpath) {
148
                    continue;
149
                }
150
            } else if (!this.combine) {
151
                continue;
152
            }
153
            if (!mod.combine && mod.ext) {
154
                continue;
155
            }
156
 
157
            // YUI core modules => core group
158
            if (!mod.group) {
159
                key = 'c' + SUB_GROUP_DELIM + YUI.version;
160
            }
161
            // YUI gallery modules => gallery group
162
            else if (mod.group === 'gallery') {
163
                if (!galleryVersion) {
164
                    galleryMatch   = GALLERY_RE.exec(this.groups.gallery.root);
165
                    galleryVersion = galleryMatch && galleryMatch[1];
166
                }
167
                name = name.split('gallery-').pop(); // remove prefix
168
                key  = 'g' + SUB_GROUP_DELIM + galleryVersion;
169
            }
170
            // If the module was built the YUI way, then we segment these modules
171
            // into the `root` group.
172
            else if (mod.path.indexOf(name + '/' + name) === 0) {
173
                key = meta.root;
174
 
175
                // Trim '/' from both ends.
176
                if (key.charAt(0) === '/') {
177
                    key = key.slice(1);
178
                }
179
                if (key.charAt(key.length - 1) === '/') {
180
                    key = key.slice(0, -1);
181
                }
182
 
183
                key = 'r' + SUB_GROUP_DELIM + key;
184
            }
185
            // If the path does not follow the YUI build convention, then we
186
            // add them to the prefix tree and subsequently segment these modules
187
            // into the `path` group.
188
            else {
189
                // remove file extension
190
                name = mod.path.split(EXTENSION_RE).shift();
191
 
192
                if (meta && meta.root) {
193
                    name = meta.root + name;
194
                }
195
 
196
                if (name.charAt(0) === '/') {
197
                    name = name.slice(1);
198
                }
199
 
200
                // Tag this module as `path` so that we know to include the
201
                // full path in the combo url later on
202
                key = 'path' + SUB_GROUP_DELIM + name;
203
            }
204
 
205
            source[key] = source[key] || [];
206
            source[key].push(name);
207
        }
208
        return source;
209
    },
210
 
211
    /**
212
    Build each combo url from the bottom up. There's probably room for optimization
213
    here, but let's keep it simple for now.
214
    @method _buildCombo
215
    @param {Array} groups Grouped module meta.
216
    @param {String} comboBase The base of the combo url.
217
    @param {String} comboTail The tail of the combo url (e.g. .debug.js).
218
    @return {String} A combo url.
219
    @private
220
    */
221
    _buildCombo: function (groups, comboBase, comboTail) {
222
        var comboUrl = comboBase,
223
            currLen  = comboBase.length + comboTail.length,
224
            currDelim,
225
            currKey,
226
            prepend,
227
            modules,
228
            token,
229
            group,
230
            len,
231
            i;
232
 
233
        for (i = 0, len = groups.length; i < len; i += 1) {
234
            group       = groups[i];
235
            currDelim   = comboUrl === comboBase ? '' : GROUP_DELIM;
236
            currKey     = group.key;
237
            modules     = group.modules;
238
 
239
            while (modules.length) {
240
                prepend = currDelim + currKey;
241
                prepend = prepend ? prepend + SUB_GROUP_DELIM : MODULE_DELIM;
242
 
243
                // Since modules with custom paths are treated as their own
244
                // segment, we override the prepend value so that it is only ever
245
                // set to the group delimiter. TODO: refactor this while loop into
246
                // one with multiple if-statements to make it easier to read.
247
                if (group.key.indexOf('path') === 0) {
248
                    prepend = currDelim;
249
                }
250
 
251
                token = prepend + modules[0];
252
 
253
                if (currLen + token.length < this.maxURLLength) {
254
                    comboUrl += token;
255
                    currLen  += token.length;
256
                    modules.shift();
257
                } else {
258
                    return comboUrl + comboTail;
259
                }
260
 
261
                currDelim = currKey = '';
262
            }
263
        }
264
 
265
        comboUrl += comboTail;
266
 
267
        // If no modules were encoded in the combo url.
268
        if (comboUrl.length === comboBase.length + comboTail.length) {
269
            comboUrl = null;
270
        }
271
 
272
        return comboUrl;
273
    },
274
 
275
    /**
276
    Sort the aggregated groups, and the modules within them. Minimizes cache misses
277
    in Yahoo's infrastructure by encoding predictable combo urls across browsers
278
    since iterating over an object does not guarantee order.
279
    @method _sortAggregatedGroups
280
    @param {Object} groups Aggregated groups.
281
    @return {Array} Sorted groups.
282
    @private
283
    **/
284
    _sortAggregatedGroups: function (groups) {
285
        var sorted = [],
286
            key,
287
            len,
288
            i;
289
 
290
        for (key in groups) {
291
            if (groups.hasOwnProperty(key)) {
292
                sorted.push({
293
                    key: key,
294
                    modules: groups[key]
295
                });
296
            }
297
        }
298
 
299
        // Sort the groups.
300
        sorted.sort(function (a, b) {
301
            if(a.key < b.key) {
302
                return -1;
303
            } else if (a.key > b.key) {
304
                return 1;
305
            } else {
306
                return 0;
307
            }
308
        });
309
 
310
        // Sort the modules.
311
        for (i = 0, len = sorted.length; i < len; i += 1) {
312
            sorted[i].modules.sort();
313
        }
314
 
315
        return sorted;
316
    }
317
}, true);
318
 
319
 
320
}, '3.18.1');