Completed
Pull Request — master (#11)
by Anton
02:51
created

public/js/vendor/text.js   F

Complexity

Total Complexity 84
Complexity/F 4

Size

Lines of Code 381
Function Count 21

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 0
c 1
b 0
f 0
nc 135790592
dl 0
loc 381
rs 3.12
wmc 84
mnd 5
bc 68
fnc 21
bpm 3.238
cpm 4
noi 6

How to fix   Complexity   

Complexity

Complex classes like public/js/vendor/text.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * @license RequireJS text 2.0.13+ Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
3
 * Available via the MIT or new BSD license.
4
 * see: http://github.com/requirejs/text for details
5
 */
6
/*jslint regexp: true */
7
/*global require, XMLHttpRequest, ActiveXObject,
8
  define, window, process, Packages,
9
  java, location, Components, FileUtils */
10
11
define(['module'], function (module) {
12
    'use strict';
13
14
    var text, fs, Cc, Ci, xpcIsWindows,
15
        progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
16
        xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
17
        bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
18
        hasLocation = typeof location !== 'undefined' && location.href,
19
        defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
20
        defaultHostName = hasLocation && location.hostname,
21
        defaultPort = hasLocation && (location.port || undefined),
22
        buildMap = {},
23
        masterConfig = (module.config && module.config()) || {};
24
25
    text = {
26
        version: '2.0.13+',
27
28
        strip: function (content) {
29
            //Strips <?xml ...?> declarations so that external SVG and XML
30
            //documents can be added to a document without worry. Also, if the string
31
            //is an HTML document, only the part inside the body tag is returned.
32
            if (content) {
33
                content = content.replace(xmlRegExp, "");
34
                var matches = content.match(bodyRegExp);
35
                if (matches) {
36
                    content = matches[1];
37
                }
38
            } else {
39
                content = "";
40
            }
41
            return content;
42
        },
43
44
        jsEscape: function (content) {
45
            return content.replace(/(['\\])/g, '\\$1')
46
                .replace(/[\f]/g, "\\f")
47
                .replace(/[\b]/g, "\\b")
48
                .replace(/[\n]/g, "\\n")
49
                .replace(/[\t]/g, "\\t")
50
                .replace(/[\r]/g, "\\r")
51
                .replace(/[\u2028]/g, "\\u2028")
52
                .replace(/[\u2029]/g, "\\u2029");
53
        },
54
55
        createXhr: masterConfig.createXhr || function () {
56
            //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
57
            var xhr, i, progId;
58
            if (typeof XMLHttpRequest !== "undefined") {
59
                return new XMLHttpRequest();
60
            } else if (typeof ActiveXObject !== "undefined") {
61
                for (i = 0; i < 3; i += 1) {
62
                    progId = progIds[i];
63
                    try {
64
                        xhr = new ActiveXObject(progId);
65
                    } catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
66
67
                    if (xhr) {
68
                        progIds = [progId];  // so faster next time
69
                        break;
70
                    }
71
                }
72
            }
73
74
            return xhr;
0 ignored issues
show
Bug introduced by
The variable xhr seems to not be initialized for all possible execution paths.
Loading history...
75
        },
76
77
        /**
78
         * Parses a resource name into its component parts. Resource names
79
         * look like: module/name.ext!strip, where the !strip part is
80
         * optional.
81
         * @param {String} name the resource name
82
         * @returns {Object} with properties "moduleName", "ext" and "strip"
83
         * where strip is a boolean.
84
         */
85
        parseName: function (name) {
86
            var modName, ext, temp,
87
                strip = false,
88
                index = name.lastIndexOf("."),
89
                isRelative = name.indexOf('./') === 0 ||
90
                             name.indexOf('../') === 0;
91
92
            if (index !== -1 && (!isRelative || index > 1)) {
93
                modName = name.substring(0, index);
94
                ext = name.substring(index + 1);
95
            } else {
96
                modName = name;
97
            }
98
99
            temp = ext || modName;
100
            index = temp.indexOf("!");
101
            if (index !== -1) {
102
                //Pull off the strip arg.
103
                strip = temp.substring(index + 1) === "strip";
104
                temp = temp.substring(0, index);
105
                if (ext) {
106
                    ext = temp;
107
                } else {
108
                    modName = temp;
109
                }
110
            }
111
112
            return {
113
                moduleName: modName,
114
                ext: ext,
0 ignored issues
show
Bug introduced by
The variable ext seems to not be initialized for all possible execution paths.
Loading history...
115
                strip: strip
116
            };
117
        },
118
119
        xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
120
121
        /**
122
         * Is an URL on another domain. Only works for browser use, returns
123
         * false in non-browser environments. Only used to know if an
124
         * optimized .js version of a text resource should be loaded
125
         * instead.
126
         * @param {String} url
127
         * @returns Boolean
128
         */
129
        useXhr: function (url, protocol, hostname, port) {
130
            var uProtocol, uHostName, uPort,
131
                match = text.xdRegExp.exec(url);
132
            if (!match) {
133
                return true;
134
            }
135
            uProtocol = match[2];
136
            uHostName = match[3];
137
138
            uHostName = uHostName.split(':');
139
            uPort = uHostName[1];
140
            uHostName = uHostName[0];
141
142
            return (!uProtocol || uProtocol === protocol) &&
143
                   (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
144
                   ((!uPort && !uHostName) || uPort === port);
145
        },
146
147
        finishLoad: function (name, strip, content, onLoad) {
148
            content = strip ? text.strip(content) : content;
149
            if (masterConfig.isBuild) {
150
                buildMap[name] = content;
151
            }
152
            onLoad(content);
153
        },
154
155
        load: function (name, req, onLoad, config) {
156
            //Name has format: some.module.filext!strip
157
            //The strip part is optional.
158
            //if strip is present, then that means only get the string contents
159
            //inside a body tag in an HTML string. For XML/SVG content it means
160
            //removing the <?xml ...?> declarations so the content can be inserted
161
            //into the current doc without problems.
162
163
            // Do not bother with the work if a build and text will
164
            // not be inlined.
165
            if (config && config.isBuild && !config.inlineText) {
166
                onLoad();
167
                return;
168
            }
169
170
            masterConfig.isBuild = config && config.isBuild;
171
172
            var parsed = text.parseName(name),
173
                nonStripName = parsed.moduleName +
174
                    (parsed.ext ? '.' + parsed.ext : ''),
175
                url = req.toUrl(nonStripName),
176
                useXhr = (masterConfig.useXhr) ||
177
                         text.useXhr;
178
179
            // Do not load if it is an empty: url
180
            if (url.indexOf('empty:') === 0) {
181
                onLoad();
182
                return;
183
            }
184
185
            //Load the text. Use XHR if possible and in a browser.
186
            if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
187
                text.get(url, function (content) {
188
                    text.finishLoad(name, parsed.strip, content, onLoad);
189
                }, function (err) {
190
                    if (onLoad.error) {
191
                        onLoad.error(err);
192
                    }
193
                });
194
            } else {
195
                //Need to fetch the resource across domains. Assume
196
                //the resource has been optimized into a JS module. Fetch
197
                //by the module name + extension, but do not include the
198
                //!strip part to avoid file system issues.
199
                req([nonStripName], function (content) {
200
                    text.finishLoad(parsed.moduleName + '.' + parsed.ext,
201
                                    parsed.strip, content, onLoad);
202
                });
203
            }
204
        },
205
206
        write: function (pluginName, moduleName, write, config) {
0 ignored issues
show
Unused Code introduced by
The parameter config is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
207
            if (buildMap.hasOwnProperty(moduleName)) {
208
                var content = text.jsEscape(buildMap[moduleName]);
209
                write.asModule(pluginName + "!" + moduleName,
210
                               "define(function () { return '" +
211
                                   content +
212
                               "';});\n");
213
            }
214
        },
215
216
        writeFile: function (pluginName, moduleName, req, write, config) {
217
            var parsed = text.parseName(moduleName),
218
                extPart = parsed.ext ? '.' + parsed.ext : '',
219
                nonStripName = parsed.moduleName + extPart,
220
                //Use a '.js' file name so that it indicates it is a
221
                //script that can be loaded across domains.
222
                fileName = req.toUrl(parsed.moduleName + extPart) + '.js';
223
224
            //Leverage own load() method to load plugin value, but only
225
            //write out values that do not have the strip argument,
226
            //to avoid any potential issues with ! in file names.
227
            text.load(nonStripName, req, function (value) {
0 ignored issues
show
Unused Code introduced by
The parameter value is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
228
                //Use own write() method to construct full module value.
229
                //But need to create shell that translates writeFile's
230
                //write() to the right interface.
231
                var textWrite = function (contents) {
232
                    return write(fileName, contents);
233
                };
234
                textWrite.asModule = function (moduleName, contents) {
235
                    return write.asModule(moduleName, fileName, contents);
236
                };
237
238
                text.write(pluginName, nonStripName, textWrite, config);
239
            }, config);
240
        }
241
    };
242
243
    if (masterConfig.env === 'node' || (!masterConfig.env &&
244
            typeof process !== "undefined" &&
245
            process.versions &&
246
            !!process.versions.node &&
247
            !process.versions['node-webkit'] &&
248
            !process.versions['atom-shell'])) {
249
        //Using special require.nodeRequire, something added by r.js.
250
        fs = require.nodeRequire('fs');
251
252
        text.get = function (url, callback, errback) {
253
            try {
254
                var file = fs.readFileSync(url, 'utf8');
255
                //Remove BOM (Byte Mark Order) from utf8 files if it is there.
256
                if (file[0] === '\uFEFF') {
257
                    file = file.substring(1);
258
                }
259
                callback(file);
260
            } catch (e) {
261
                if (errback) {
262
                    errback(e);
263
                }
264
            }
265
        };
266
    } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
267
            text.createXhr())) {
268
        text.get = function (url, callback, errback, headers) {
269
            var xhr = text.createXhr(), header;
270
            xhr.open('GET', url, true);
271
272
            //Allow plugins direct access to xhr headers
273
            if (headers) {
274
                for (header in headers) {
275
                    if (headers.hasOwnProperty(header)) {
276
                        xhr.setRequestHeader(header.toLowerCase(), headers[header]);
277
                    }
278
                }
279
            }
280
281
            //Allow overrides specified in config
282
            if (masterConfig.onXhr) {
283
                masterConfig.onXhr(xhr, url);
284
            }
285
286
            xhr.onreadystatechange = function (evt) {
0 ignored issues
show
Unused Code introduced by
The parameter evt is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
287
                var status, err;
288
                //Do not explicitly handle errors, those should be
289
                //visible via console output in the browser.
290
                if (xhr.readyState === 4) {
291
                    status = xhr.status || 0;
292
                    if (status > 399 && status < 600) {
293
                        //An http 4xx or 5xx error. Signal an error.
294
                        err = new Error(url + ' HTTP status: ' + status);
295
                        err.xhr = xhr;
296
                        if (errback) {
297
                            errback(err);
298
                        }
299
                    } else {
300
                        callback(xhr.responseText);
301
                    }
302
303
                    if (masterConfig.onXhrComplete) {
304
                        masterConfig.onXhrComplete(xhr, url);
305
                    }
306
                }
307
            };
308
            xhr.send(null);
309
        };
310
    } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
311
            typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
312
        //Why Java, why is this so awkward?
313
        text.get = function (url, callback) {
314
            var stringBuffer, line,
315
                encoding = "utf-8",
316
                file = new java.io.File(url),
317
                lineSeparator = java.lang.System.getProperty("line.separator"),
318
                input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
319
                content = '';
320
            try {
321
                stringBuffer = new java.lang.StringBuffer();
322
                line = input.readLine();
323
324
                // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
325
                // http://www.unicode.org/faq/utf_bom.html
326
327
                // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
328
                // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
329
                if (line && line.length() && line.charAt(0) === 0xfeff) {
330
                    // Eat the BOM, since we've already found the encoding on this file,
331
                    // and we plan to concatenating this buffer with others; the BOM should
332
                    // only appear at the top of a file.
333
                    line = line.substring(1);
334
                }
335
336
                if (line !== null) {
337
                    stringBuffer.append(line);
338
                }
339
340
                while ((line = input.readLine()) !== null) {
341
                    stringBuffer.append(lineSeparator);
342
                    stringBuffer.append(line);
343
                }
344
                //Make sure we return a JavaScript string and not a Java string.
345
                content = String(stringBuffer.toString()); //String
346
            } finally {
347
                input.close();
348
            }
349
            callback(content);
350
        };
351
    } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&
352
            typeof Components !== 'undefined' && Components.classes &&
353
            Components.interfaces)) {
354
        //Avert your gaze!
355
        Cc = Components.classes;
356
        Ci = Components.interfaces;
357
        Components.utils['import']('resource://gre/modules/FileUtils.jsm');
358
        xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);
359
360
        text.get = function (url, callback) {
361
            var inStream, convertStream, fileObj,
362
                readData = {};
363
364
            if (xpcIsWindows) {
365
                url = url.replace(/\//g, '\\');
366
            }
367
368
            fileObj = new FileUtils.File(url);
369
370
            //XPCOM, you so crazy
371
            try {
372
                inStream = Cc['@mozilla.org/network/file-input-stream;1']
373
                           .createInstance(Ci.nsIFileInputStream);
374
                inStream.init(fileObj, 1, 0, false);
375
376
                convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']
377
                                .createInstance(Ci.nsIConverterInputStream);
378
                convertStream.init(inStream, "utf-8", inStream.available(),
379
                Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
380
381
                convertStream.readString(inStream.available(), readData);
382
                convertStream.close();
383
                inStream.close();
384
                callback(readData.value);
385
            } catch (e) {
386
                throw new Error((fileObj && fileObj.path || '') + ': ' + e);
387
            }
388
        };
389
    }
390
    return text;
391
});