]>
Commit | Line | Data |
---|---|---|
53ed6d7d | 1 | /** |
2 | * @license RequireJS text 2.0.12 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.12', | |
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) {} | |
66 | ||
67 | if (xhr) { | |
68 | progIds = [progId]; // so faster next time | |
69 | break; | |
70 | } | |
71 | } | |
72 | } | |
73 | ||
74 | return xhr; | |
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.indexOf("."), | |
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, name.length); | |
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, | |
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) { | |
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) { | |
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 | //Using special require.nodeRequire, something added by r.js. | |
249 | fs = require.nodeRequire('fs'); | |
250 | ||
251 | text.get = function (url, callback, errback) { | |
252 | try { | |
253 | var file = fs.readFileSync(url, 'utf8'); | |
254 | //Remove BOM (Byte Mark Order) from utf8 files if it is there. | |
255 | if (file.indexOf('\uFEFF') === 0) { | |
256 | file = file.substring(1); | |
257 | } | |
258 | callback(file); | |
259 | } catch (e) { | |
260 | if (errback) { | |
261 | errback(e); | |
262 | } | |
263 | } | |
264 | }; | |
265 | } else if (masterConfig.env === 'xhr' || (!masterConfig.env && | |
266 | text.createXhr())) { | |
267 | text.get = function (url, callback, errback, headers) { | |
268 | var xhr = text.createXhr(), header; | |
269 | xhr.open('GET', url, true); | |
270 | ||
271 | //Allow plugins direct access to xhr headers | |
272 | if (headers) { | |
273 | for (header in headers) { | |
274 | if (headers.hasOwnProperty(header)) { | |
275 | xhr.setRequestHeader(header.toLowerCase(), headers[header]); | |
276 | } | |
277 | } | |
278 | } | |
279 | ||
280 | //Allow overrides specified in config | |
281 | if (masterConfig.onXhr) { | |
282 | masterConfig.onXhr(xhr, url); | |
283 | } | |
284 | ||
285 | xhr.onreadystatechange = function (evt) { | |
286 | var status, err; | |
287 | //Do not explicitly handle errors, those should be | |
288 | //visible via console output in the browser. | |
289 | if (xhr.readyState === 4) { | |
290 | status = xhr.status || 0; | |
291 | if (status > 399 && status < 600) { | |
292 | //An http 4xx or 5xx error. Signal an error. | |
293 | err = new Error(url + ' HTTP status: ' + status); | |
294 | err.xhr = xhr; | |
295 | if (errback) { | |
296 | errback(err); | |
297 | } | |
298 | } else { | |
299 | callback(xhr.responseText); | |
300 | } | |
301 | ||
302 | if (masterConfig.onXhrComplete) { | |
303 | masterConfig.onXhrComplete(xhr, url); | |
304 | } | |
305 | } | |
306 | }; | |
307 | xhr.send(null); | |
308 | }; | |
309 | } else if (masterConfig.env === 'rhino' || (!masterConfig.env && | |
310 | typeof Packages !== 'undefined' && typeof java !== 'undefined')) { | |
311 | //Why Java, why is this so awkward? | |
312 | text.get = function (url, callback) { | |
313 | var stringBuffer, line, | |
314 | encoding = "utf-8", | |
315 | file = new java.io.File(url), | |
316 | lineSeparator = java.lang.System.getProperty("line.separator"), | |
317 | input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), | |
318 | content = ''; | |
319 | try { | |
320 | stringBuffer = new java.lang.StringBuffer(); | |
321 | line = input.readLine(); | |
322 | ||
323 | // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 | |
324 | // http://www.unicode.org/faq/utf_bom.html | |
325 | ||
326 | // 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: | |
327 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 | |
328 | if (line && line.length() && line.charAt(0) === 0xfeff) { | |
329 | // Eat the BOM, since we've already found the encoding on this file, | |
330 | // and we plan to concatenating this buffer with others; the BOM should | |
331 | // only appear at the top of a file. | |
332 | line = line.substring(1); | |
333 | } | |
334 | ||
335 | if (line !== null) { | |
336 | stringBuffer.append(line); | |
337 | } | |
338 | ||
339 | while ((line = input.readLine()) !== null) { | |
340 | stringBuffer.append(lineSeparator); | |
341 | stringBuffer.append(line); | |
342 | } | |
343 | //Make sure we return a JavaScript string and not a Java string. | |
344 | content = String(stringBuffer.toString()); //String | |
345 | } finally { | |
346 | input.close(); | |
347 | } | |
348 | callback(content); | |
349 | }; | |
350 | } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env && | |
351 | typeof Components !== 'undefined' && Components.classes && | |
352 | Components.interfaces)) { | |
353 | //Avert your gaze! | |
354 | Cc = Components.classes; | |
355 | Ci = Components.interfaces; | |
356 | Components.utils['import']('resource://gre/modules/FileUtils.jsm'); | |
357 | xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc); | |
358 | ||
359 | text.get = function (url, callback) { | |
360 | var inStream, convertStream, fileObj, | |
361 | readData = {}; | |
362 | ||
363 | if (xpcIsWindows) { | |
364 | url = url.replace(/\//g, '\\'); | |
365 | } | |
366 | ||
367 | fileObj = new FileUtils.File(url); | |
368 | ||
369 | //XPCOM, you so crazy | |
370 | try { | |
371 | inStream = Cc['@mozilla.org/network/file-input-stream;1'] | |
372 | .createInstance(Ci.nsIFileInputStream); | |
373 | inStream.init(fileObj, 1, 0, false); | |
374 | ||
375 | convertStream = Cc['@mozilla.org/intl/converter-input-stream;1'] | |
376 | .createInstance(Ci.nsIConverterInputStream); | |
377 | convertStream.init(inStream, "utf-8", inStream.available(), | |
378 | Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); | |
379 | ||
380 | convertStream.readString(inStream.available(), readData); | |
381 | convertStream.close(); | |
382 | inStream.close(); | |
383 | callback(readData.value); | |
384 | } catch (e) { | |
385 | throw new Error((fileObj && fileObj.path || '') + ': ' + e); | |
386 | } | |
387 | }; | |
388 | } | |
389 | return text; | |
390 | }); |