text.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /**
  2. * @license RequireJS text 2.0.5 Copyright (c) 2010-2012, 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: false, XMLHttpRequest: false, ActiveXObject: false,
  8. define: false, window: false, process: false, Packages: false,
  9. java: false, location: false */
  10. define(['module'], function (module) {
  11. 'use strict';
  12. var text, fs,
  13. progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
  14. xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
  15. bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
  16. hasLocation = typeof location !== 'undefined' && location.href,
  17. defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
  18. defaultHostName = hasLocation && location.hostname,
  19. defaultPort = hasLocation && (location.port || undefined),
  20. buildMap = [],
  21. masterConfig = (module.config && module.config()) || {};
  22. text = {
  23. version: '2.0.5',
  24. strip: function (content) {
  25. //Strips xml declarations so that external SVG and XML
  26. //documents can be added to a document without worry. Also, if the string
  27. //is an HTML document, only the part inside the body tag is returned.
  28. if (content) {
  29. content = content.replace(xmlRegExp, "");
  30. var matches = content.match(bodyRegExp);
  31. if (matches) {
  32. content = matches[1];
  33. }
  34. } else {
  35. content = "";
  36. }
  37. return content;
  38. },
  39. jsEscape: function (content) {
  40. return content.replace(/(['\\])/g, '\\$1')
  41. .replace(/[\f]/g, "\\f")
  42. .replace(/[\b]/g, "\\b")
  43. .replace(/[\n]/g, "\\n")
  44. .replace(/[\t]/g, "\\t")
  45. .replace(/[\r]/g, "\\r")
  46. .replace(/[\u2028]/g, "\\u2028")
  47. .replace(/[\u2029]/g, "\\u2029");
  48. },
  49. createXhr: masterConfig.createXhr || function () {
  50. //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
  51. var xhr, i, progId;
  52. if (typeof XMLHttpRequest !== "undefined") {
  53. return new XMLHttpRequest();
  54. } else if (typeof ActiveXObject !== "undefined") {
  55. for (i = 0; i < 3; i += 1) {
  56. progId = progIds[i];
  57. try {
  58. xhr = new ActiveXObject(progId);
  59. } catch (e) {}
  60. if (xhr) {
  61. progIds = [progId]; // so faster next time
  62. break;
  63. }
  64. }
  65. }
  66. return xhr;
  67. },
  68. /**
  69. * Parses a resource name into its component parts. Resource names
  70. * look like: module/name.ext!strip, where the !strip part is
  71. * optional.
  72. * @param {String} name the resource name
  73. * @returns {Object} with properties "moduleName", "ext" and "strip"
  74. * where strip is a boolean.
  75. */
  76. parseName: function (name) {
  77. var modName, ext, temp,
  78. strip = false,
  79. index = name.indexOf("."),
  80. isRelative = name.indexOf('./') === 0 ||
  81. name.indexOf('../') === 0;
  82. if (index !== -1 && (!isRelative || index > 1)) {
  83. modName = name.substring(0, index);
  84. ext = name.substring(index + 1, name.length);
  85. } else {
  86. modName = name;
  87. }
  88. temp = ext || modName;
  89. index = temp.indexOf("!");
  90. if (index !== -1) {
  91. //Pull off the strip arg.
  92. strip = temp.substring(index + 1) === "strip";
  93. temp = temp.substring(0, index);
  94. if (ext) {
  95. ext = temp;
  96. } else {
  97. modName = temp;
  98. }
  99. }
  100. return {
  101. moduleName: modName,
  102. ext: ext,
  103. strip: strip
  104. };
  105. },
  106. xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
  107. /**
  108. * Is an URL on another domain. Only works for browser use, returns
  109. * false in non-browser environments. Only used to know if an
  110. * optimized .js version of a text resource should be loaded
  111. * instead.
  112. * @param {String} url
  113. * @returns Boolean
  114. */
  115. useXhr: function (url, protocol, hostname, port) {
  116. var uProtocol, uHostName, uPort,
  117. match = text.xdRegExp.exec(url);
  118. if (!match) {
  119. return true;
  120. }
  121. uProtocol = match[2];
  122. uHostName = match[3];
  123. uHostName = uHostName.split(':');
  124. uPort = uHostName[1];
  125. uHostName = uHostName[0];
  126. return (!uProtocol || uProtocol === protocol) &&
  127. (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
  128. ((!uPort && !uHostName) || uPort === port);
  129. },
  130. finishLoad: function (name, strip, content, onLoad) {
  131. content = strip ? text.strip(content) : content;
  132. if (masterConfig.isBuild) {
  133. buildMap[name] = content;
  134. }
  135. onLoad(content);
  136. },
  137. load: function (name, req, onLoad, config) {
  138. //Name has format: some.module.filext!strip
  139. //The strip part is optional.
  140. //if strip is present, then that means only get the string contents
  141. //inside a body tag in an HTML string. For XML/SVG content it means
  142. //removing the xml declarations so the content can be inserted
  143. //into the current doc without problems.
  144. // Do not bother with the work if a build and text will
  145. // not be inlined.
  146. if (config.isBuild && !config.inlineText) {
  147. onLoad();
  148. return;
  149. }
  150. masterConfig.isBuild = config.isBuild;
  151. var parsed = text.parseName(name),
  152. nonStripName = parsed.moduleName +
  153. (parsed.ext ? '.' + parsed.ext : ''),
  154. url = req.toUrl(nonStripName),
  155. useXhr = (masterConfig.useXhr) ||
  156. text.useXhr;
  157. //Load the text. Use XHR if possible and in a browser.
  158. if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
  159. text.get(url, function (content) {
  160. text.finishLoad(name, parsed.strip, content, onLoad);
  161. }, function (err) {
  162. if (onLoad.error) {
  163. onLoad.error(err);
  164. }
  165. });
  166. } else {
  167. //Need to fetch the resource across domains. Assume
  168. //the resource has been optimized into a JS module. Fetch
  169. //by the module name + extension, but do not include the
  170. //!strip part to avoid file system issues.
  171. req([nonStripName], function (content) {
  172. text.finishLoad(parsed.moduleName + '.' + parsed.ext,
  173. parsed.strip, content, onLoad);
  174. });
  175. }
  176. },
  177. write: function (pluginName, moduleName, write, config) {
  178. if (buildMap.hasOwnProperty(moduleName)) {
  179. var content = text.jsEscape(buildMap[moduleName]);
  180. write.asModule(pluginName + "!" + moduleName,
  181. "define(function () { return '" +
  182. content +
  183. "';});\n");
  184. }
  185. },
  186. writeFile: function (pluginName, moduleName, req, write, config) {
  187. var parsed = text.parseName(moduleName),
  188. extPart = parsed.ext ? '.' + parsed.ext : '',
  189. nonStripName = parsed.moduleName + extPart,
  190. //Use a '.js' file name so that it indicates it is a
  191. //script that can be loaded across domains.
  192. fileName = req.toUrl(parsed.moduleName + extPart) + '.js';
  193. //Leverage own load() method to load plugin value, but only
  194. //write out values that do not have the strip argument,
  195. //to avoid any potential issues with ! in file names.
  196. text.load(nonStripName, req, function (value) {
  197. //Use own write() method to construct full module value.
  198. //But need to create shell that translates writeFile's
  199. //write() to the right interface.
  200. var textWrite = function (contents) {
  201. return write(fileName, contents);
  202. };
  203. textWrite.asModule = function (moduleName, contents) {
  204. return write.asModule(moduleName, fileName, contents);
  205. };
  206. text.write(pluginName, nonStripName, textWrite, config);
  207. }, config);
  208. }
  209. };
  210. if (masterConfig.env === 'node' || (!masterConfig.env &&
  211. typeof process !== "undefined" &&
  212. process.versions &&
  213. !!process.versions.node)) {
  214. //Using special require.nodeRequire, something added by r.js.
  215. fs = require.nodeRequire('fs');
  216. text.get = function (url, callback) {
  217. var file = fs.readFileSync(url, 'utf8');
  218. //Remove BOM (Byte Mark Order) from utf8 files if it is there.
  219. if (file.indexOf('\uFEFF') === 0) {
  220. file = file.substring(1);
  221. }
  222. callback(file);
  223. };
  224. } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
  225. text.createXhr())) {
  226. text.get = function (url, callback, errback, headers) {
  227. var xhr = text.createXhr(), header;
  228. xhr.open('GET', url, true);
  229. //Allow plugins direct access to xhr headers
  230. if (headers) {
  231. for (header in headers) {
  232. if (headers.hasOwnProperty(header)) {
  233. xhr.setRequestHeader(header.toLowerCase(), headers[header]);
  234. }
  235. }
  236. }
  237. //Allow overrides specified in config
  238. if (masterConfig.onXhr) {
  239. masterConfig.onXhr(xhr, url);
  240. }
  241. xhr.onreadystatechange = function (evt) {
  242. var status, err;
  243. //Do not explicitly handle errors, those should be
  244. //visible via console output in the browser.
  245. if (xhr.readyState === 4) {
  246. status = xhr.status;
  247. if (status > 399 && status < 600) {
  248. //An http 4xx or 5xx error. Signal an error.
  249. err = new Error(url + ' HTTP status: ' + status);
  250. err.xhr = xhr;
  251. errback(err);
  252. } else {
  253. callback(xhr.responseText);
  254. }
  255. }
  256. };
  257. xhr.send(null);
  258. };
  259. } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
  260. typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
  261. //Why Java, why is this so awkward?
  262. text.get = function (url, callback) {
  263. var stringBuffer, line,
  264. encoding = "utf-8",
  265. file = new java.io.File(url),
  266. lineSeparator = java.lang.System.getProperty("line.separator"),
  267. input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
  268. content = '';
  269. try {
  270. stringBuffer = new java.lang.StringBuffer();
  271. line = input.readLine();
  272. // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
  273. // http://www.unicode.org/faq/utf_bom.html
  274. // 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:
  275. // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
  276. if (line && line.length() && line.charAt(0) === 0xfeff) {
  277. // Eat the BOM, since we've already found the encoding on this file,
  278. // and we plan to concatenating this buffer with others; the BOM should
  279. // only appear at the top of a file.
  280. line = line.substring(1);
  281. }
  282. stringBuffer.append(line);
  283. while ((line = input.readLine()) !== null) {
  284. stringBuffer.append(lineSeparator);
  285. stringBuffer.append(line);
  286. }
  287. //Make sure we return a JavaScript string and not a Java string.
  288. content = String(stringBuffer.toString()); //String
  289. } finally {
  290. input.close();
  291. }
  292. callback(content);
  293. };
  294. }
  295. return text;
  296. });