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