livereload.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. (function() {
  2. var Connector, LiveReload, Options, ProtocolError, Reloader, Timer,
  3. hasProp = {}.hasOwnProperty;
  4. Connector = require('./connector').Connector;
  5. Timer = require('./timer').Timer;
  6. Options = require('./options').Options;
  7. Reloader = require('./reloader').Reloader;
  8. ProtocolError = require('./protocol').ProtocolError;
  9. exports.LiveReload = LiveReload = (function() {
  10. function LiveReload(window1) {
  11. var k, ref, v;
  12. this.window = window1;
  13. this.listeners = {};
  14. this.plugins = [];
  15. this.pluginIdentifiers = {};
  16. this.console = this.window.console && this.window.console.log && this.window.console.error ? this.window.location.href.match(/LR-verbose/) ? this.window.console : {
  17. log: function() {},
  18. error: this.window.console.error.bind(this.window.console)
  19. } : {
  20. log: function() {},
  21. error: function() {}
  22. };
  23. if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) {
  24. this.console.error("LiveReload disabled because the browser does not seem to support web sockets");
  25. return;
  26. }
  27. if ('LiveReloadOptions' in window) {
  28. this.options = new Options();
  29. ref = window['LiveReloadOptions'];
  30. for (k in ref) {
  31. if (!hasProp.call(ref, k)) continue;
  32. v = ref[k];
  33. this.options.set(k, v);
  34. }
  35. } else {
  36. this.options = Options.extract(this.window.document);
  37. if (!this.options) {
  38. this.console.error("LiveReload disabled because it could not find its own <SCRIPT> tag");
  39. return;
  40. }
  41. }
  42. this.reloader = new Reloader(this.window, this.console, Timer);
  43. this.connector = new Connector(this.options, this.WebSocket, Timer, {
  44. connecting: (function(_this) {
  45. return function() {};
  46. })(this),
  47. socketConnected: (function(_this) {
  48. return function() {};
  49. })(this),
  50. connected: (function(_this) {
  51. return function(protocol) {
  52. var base;
  53. if (typeof (base = _this.listeners).connect === "function") {
  54. base.connect();
  55. }
  56. _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ").");
  57. return _this.analyze();
  58. };
  59. })(this),
  60. error: (function(_this) {
  61. return function(e) {
  62. if (e instanceof ProtocolError) {
  63. if (typeof console !== "undefined" && console !== null) {
  64. return console.log(e.message + ".");
  65. }
  66. } else {
  67. if (typeof console !== "undefined" && console !== null) {
  68. return console.log("LiveReload internal error: " + e.message);
  69. }
  70. }
  71. };
  72. })(this),
  73. disconnected: (function(_this) {
  74. return function(reason, nextDelay) {
  75. var base;
  76. if (typeof (base = _this.listeners).disconnect === "function") {
  77. base.disconnect();
  78. }
  79. switch (reason) {
  80. case 'cannot-connect':
  81. return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec.");
  82. case 'broken':
  83. return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec.");
  84. case 'handshake-timeout':
  85. return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec.");
  86. case 'handshake-failed':
  87. return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec.");
  88. case 'manual':
  89. break;
  90. case 'error':
  91. break;
  92. default:
  93. return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec.");
  94. }
  95. };
  96. })(this),
  97. message: (function(_this) {
  98. return function(message) {
  99. switch (message.command) {
  100. case 'reload':
  101. return _this.performReload(message);
  102. case 'alert':
  103. return _this.performAlert(message);
  104. }
  105. };
  106. })(this)
  107. });
  108. this.initialized = true;
  109. }
  110. LiveReload.prototype.on = function(eventName, handler) {
  111. return this.listeners[eventName] = handler;
  112. };
  113. LiveReload.prototype.log = function(message) {
  114. return this.console.log("" + message);
  115. };
  116. LiveReload.prototype.performReload = function(message) {
  117. var ref, ref1, ref2;
  118. this.log("LiveReload received reload request: " + (JSON.stringify(message, null, 2)));
  119. return this.reloader.reload(message.path, {
  120. liveCSS: (ref = message.liveCSS) != null ? ref : true,
  121. liveImg: (ref1 = message.liveImg) != null ? ref1 : true,
  122. reloadMissingCSS: (ref2 = message.reloadMissingCSS) != null ? ref2 : true,
  123. originalPath: message.originalPath || '',
  124. overrideURL: message.overrideURL || '',
  125. serverURL: "http://" + this.options.host + ":" + this.options.port
  126. });
  127. };
  128. LiveReload.prototype.performAlert = function(message) {
  129. return alert(message.message);
  130. };
  131. LiveReload.prototype.shutDown = function() {
  132. var base;
  133. if (!this.initialized) {
  134. return;
  135. }
  136. this.connector.disconnect();
  137. this.log("LiveReload disconnected.");
  138. return typeof (base = this.listeners).shutdown === "function" ? base.shutdown() : void 0;
  139. };
  140. LiveReload.prototype.hasPlugin = function(identifier) {
  141. return !!this.pluginIdentifiers[identifier];
  142. };
  143. LiveReload.prototype.addPlugin = function(pluginClass) {
  144. var plugin;
  145. if (!this.initialized) {
  146. return;
  147. }
  148. if (this.hasPlugin(pluginClass.identifier)) {
  149. return;
  150. }
  151. this.pluginIdentifiers[pluginClass.identifier] = true;
  152. plugin = new pluginClass(this.window, {
  153. _livereload: this,
  154. _reloader: this.reloader,
  155. _connector: this.connector,
  156. console: this.console,
  157. Timer: Timer,
  158. generateCacheBustUrl: (function(_this) {
  159. return function(url) {
  160. return _this.reloader.generateCacheBustUrl(url);
  161. };
  162. })(this)
  163. });
  164. this.plugins.push(plugin);
  165. this.reloader.addPlugin(plugin);
  166. };
  167. LiveReload.prototype.analyze = function() {
  168. var i, len, plugin, pluginData, pluginsData, ref;
  169. if (!this.initialized) {
  170. return;
  171. }
  172. if (!(this.connector.protocol >= 7)) {
  173. return;
  174. }
  175. pluginsData = {};
  176. ref = this.plugins;
  177. for (i = 0, len = ref.length; i < len; i++) {
  178. plugin = ref[i];
  179. pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {};
  180. pluginData.version = plugin.constructor.version;
  181. }
  182. this.connector.sendCommand({
  183. command: 'info',
  184. plugins: pluginsData,
  185. url: this.window.location.href
  186. });
  187. };
  188. return LiveReload;
  189. })();
  190. }).call(this);