diff --git a/VERSION b/VERSION index 815e68d..09843e3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.8 +2.0.9 diff --git a/dist/livereload.js b/dist/livereload.js index edb2802..90baabd 100644 --- a/dist/livereload.js +++ b/dist/livereload.js @@ -1,69 +1,38 @@ (function() { -var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __less = {}, __startup = {}; - -// customevents -var CustomEvents; -CustomEvents = { - bind: function(element, eventName, handler) { - if (element.addEventListener) { - return element.addEventListener(eventName, handler, false); - } else if (element.attachEvent) { - element[eventName] = 1; - return element.attachEvent('onpropertychange', function(event) { - if (event.propertyName === eventName) { - return handler(); - } - }); - } else { - throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement"); - } - }, - fire: function(element, eventName) { - var event; - if (element.addEventListener) { - event = document.createEvent('HTMLEvents'); - event.initEvent(eventName, true, true); - return document.dispatchEvent(event); - } else if (element.attachEvent) { - if (element[eventName]) { - return element[eventName]++; - } - } else { - throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement"); - } - } -}; -__customevents.bind = CustomEvents.bind; -__customevents.fire = CustomEvents.fire; +var __protocol = {}, __connector = {}, __customevents = {}, __less = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __startup = {}; // protocol -var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError; -var __indexOf = Array.prototype.indexOf || function(item) { - for (var i = 0, l = this.length; i < l; i++) { - if (this[i] === item) return i; - } - return -1; -}; +// Generated by CoffeeScript 1.6.3 +var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + __protocol.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; + __protocol.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; + __protocol.ProtocolError = ProtocolError = (function() { function ProtocolError(reason, data) { this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; } + return ProtocolError; + })(); + __protocol.Parser = Parser = (function() { function Parser(handlers) { this.handlers = handlers; this.reset(); } + Parser.prototype.reset = function() { return this.protocol = null; }; + Parser.prototype.process = function(data) { - var command, message, options, _ref; + var command, e, message, options, _ref; try { - if (!(this.protocol != null)) { + if (this.protocol == null) { if (data.match(/^!!ver:([\d.]+)$/)) { this.protocol = 6; } else if (message = this._parseMessage(data, ['hello'])) { @@ -96,7 +65,8 @@ __protocol.Parser = Parser = (function() { message = this._parseMessage(data, ['reload', 'alert']); return this.handlers.message(message); } - } catch (e) { + } catch (_error) { + e = _error; if (e instanceof ProtocolError) { return this.handlers.error(e); } else { @@ -104,11 +74,13 @@ __protocol.Parser = Parser = (function() { } } }; + Parser.prototype._parseMessage = function(data, validCommands) { - var message, _ref; + var e, message, _ref; try { message = JSON.parse(data); - } catch (e) { + } catch (_error) { + e = _error; throw new ProtocolError('unparsable JSON', data); } if (!message.command) { @@ -119,19 +91,20 @@ __protocol.Parser = Parser = (function() { } return message; }; + return Parser; + })(); // connector -// Generated by CoffeeScript 1.3.3 +// Generated by CoffeeScript 1.6.3 var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref; _ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7; -Version = '2.0.8'; +Version = '2.0.9'; __connector.Connector = Connector = (function() { - function Connector(options, WebSocket, Timer, handlers) { var _this = this; this.options = options; @@ -278,20 +251,124 @@ __connector.Connector = Connector = (function() { })(); +// customevents +// Generated by CoffeeScript 1.6.3 +var CustomEvents; + +CustomEvents = { + bind: function(element, eventName, handler) { + if (element.addEventListener) { + return element.addEventListener(eventName, handler, false); + } else if (element.attachEvent) { + element[eventName] = 1; + return element.attachEvent('onpropertychange', function(event) { + if (event.propertyName === eventName) { + return handler(); + } + }); + } else { + throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement"); + } + }, + fire: function(element, eventName) { + var event; + if (element.addEventListener) { + event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, true); + return document.dispatchEvent(event); + } else if (element.attachEvent) { + if (element[eventName]) { + return element[eventName]++; + } + } else { + throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement"); + } + } +}; + +__customevents.bind = CustomEvents.bind; + +__customevents.fire = CustomEvents.fire; + +// less +// Generated by CoffeeScript 1.6.3 +var LessPlugin; + +__less = LessPlugin = (function() { + LessPlugin.identifier = 'less'; + + LessPlugin.version = '1.0'; + + function LessPlugin(window, host) { + this.window = window; + this.host = host; + } + + LessPlugin.prototype.reload = function(path, options) { + if (this.window.less && this.window.less.refresh) { + if (path.match(/\.less$/i)) { + return this.reloadLess(path); + } + if (options.originalPath.match(/\.less$/i)) { + return this.reloadLess(options.originalPath); + } + } + return false; + }; + + LessPlugin.prototype.reloadLess = function(path) { + var link, links, _i, _len; + links = (function() { + var _i, _len, _ref, _results; + _ref = document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.href && link.rel === 'stylesheet/less' || (link.rel.match(/stylesheet/) && link.type.match(/^text\/(x-)?less$/))) { + _results.push(link); + } + } + return _results; + })(); + if (links.length === 0) { + return false; + } + for (_i = 0, _len = links.length; _i < _len; _i++) { + link = links[_i]; + link.href = this.host.generateCacheBustUrl(link.href); + } + this.host.console.log("LiveReload is asking LESS to recompile all stylesheets"); + this.window.less.refresh(true); + return true; + }; + + LessPlugin.prototype.analyze = function() { + return { + disable: !!(this.window.less && this.window.less.refresh) + }; + }; + + return LessPlugin; + +})(); + // timer +// Generated by CoffeeScript 1.6.3 var Timer; -var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + __timer.Timer = Timer = (function() { function Timer(func) { + var _this = this; this.func = func; this.running = false; this.id = null; - this._handler = __bind(function() { - this.running = false; - this.id = null; - return this.func(); - }, this); + this._handler = function() { + _this.running = false; + _this.id = null; + return _this.func(); + }; } + Timer.prototype.start = function(timeout) { if (this.running) { clearTimeout(this.id); @@ -299,6 +376,7 @@ __timer.Timer = Timer = (function() { this.id = setTimeout(this._handler, timeout); return this.running = true; }; + Timer.prototype.stop = function() { if (this.running) { clearTimeout(this.id); @@ -306,14 +384,19 @@ __timer.Timer = Timer = (function() { return this.id = null; } }; + return Timer; + })(); + Timer.start = function(timeout, func) { return setTimeout(func, timeout); }; // options +// Generated by CoffeeScript 1.6.3 var Options; + __options.Options = Options = (function() { function Options() { this.host = null; @@ -324,7 +407,9 @@ __options.Options = Options = (function() { this.mindelay = 1000; this.maxdelay = 60000; this.handshake_timeout = 5000; + this.animate = false; } + Options.prototype.set = function(name, value) { switch (typeof this[name]) { case 'undefined': @@ -335,10 +420,13 @@ __options.Options = Options = (function() { return this[name] = value; } }; + return Options; + })(); + Options.extract = function(document) { - var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len2, _ref, _ref2; + var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len1, _ref, _ref1; _ref = document.getElementsByTagName('script'); for (_i = 0, _len = _ref.length; _i < _len; _i++) { element = _ref[_i]; @@ -351,9 +439,9 @@ Options.extract = function(document) { } } if (m[2]) { - _ref2 = m[2].split('&'); - for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { - pair = _ref2[_j]; + _ref1 = m[2].split('&'); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + pair = _ref1[_j]; if ((keyAndValue = pair.split('=')).length > 1) { options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); } @@ -366,460 +454,455 @@ Options.extract = function(document) { }; // reloader -// Generated by CoffeeScript 1.3.1 -(function() { - var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; - - splitUrl = function(url) { - var hash, index, params; - if ((index = url.indexOf('#')) >= 0) { - hash = url.slice(index); - url = url.slice(0, index); - } else { - hash = ''; - } - if ((index = url.indexOf('?')) >= 0) { - params = url.slice(index); - url = url.slice(0, index); - } else { - params = ''; - } - return { - url: url, - params: params, - hash: hash - }; +// Generated by CoffeeScript 1.6.3 +var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; + +splitUrl = function(url) { + var hash, index, params; + if ((index = url.indexOf('#')) >= 0) { + hash = url.slice(index); + url = url.slice(0, index); + } else { + hash = ''; + } + if ((index = url.indexOf('?')) >= 0) { + params = url.slice(index); + url = url.slice(0, index); + } else { + params = ''; + } + return { + url: url, + params: params, + hash: hash }; +}; - pathFromUrl = function(url) { - var path; - url = splitUrl(url).url; - if (url.indexOf('file://') === 0) { - path = url.replace(/^file:\/\/(localhost)?/, ''); - } else { - path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); - } - return decodeURIComponent(path); - }; +pathFromUrl = function(url) { + var path; + url = splitUrl(url).url; + if (url.indexOf('file://') === 0) { + path = url.replace(/^file:\/\/(localhost)?/, ''); + } else { + path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); + } + return decodeURIComponent(path); +}; - pickBestMatch = function(path, objects, pathFunc) { - var bestMatch, object, score, _i, _len; - bestMatch = { - score: 0 - }; - for (_i = 0, _len = objects.length; _i < _len; _i++) { - object = objects[_i]; - score = numberOfMatchingSegments(path, pathFunc(object)); - if (score > bestMatch.score) { - bestMatch = { - object: object, - score: score - }; - } - } - if (bestMatch.score > 0) { - return bestMatch; - } else { - return null; - } +pickBestMatch = function(path, objects, pathFunc) { + var bestMatch, object, score, _i, _len; + bestMatch = { + score: 0 }; - - numberOfMatchingSegments = function(path1, path2) { - var comps1, comps2, eqCount, len; - path1 = path1.replace(/^\/+/, '').toLowerCase(); - path2 = path2.replace(/^\/+/, '').toLowerCase(); - if (path1 === path2) { - return 10000; - } - comps1 = path1.split('/').reverse(); - comps2 = path2.split('/').reverse(); - len = Math.min(comps1.length, comps2.length); - eqCount = 0; - while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { - ++eqCount; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + score = numberOfMatchingSegments(path, pathFunc(object)); + if (score > bestMatch.score) { + bestMatch = { + object: object, + score: score + }; } - return eqCount; - }; - - pathsMatch = function(path1, path2) { - return numberOfMatchingSegments(path1, path2) > 0; - }; + } + if (bestMatch.score > 0) { + return bestMatch; + } else { + return null; + } +}; - IMAGE_STYLES = [ - { - selector: 'background', - styleNames: ['backgroundImage'] - }, { - selector: 'border', - styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] - } - ]; +numberOfMatchingSegments = function(path1, path2) { + var comps1, comps2, eqCount, len; + path1 = path1.replace(/^\/+/, '').toLowerCase(); + path2 = path2.replace(/^\/+/, '').toLowerCase(); + if (path1 === path2) { + return 10000; + } + comps1 = path1.split('/').reverse(); + comps2 = path2.split('/').reverse(); + len = Math.min(comps1.length, comps2.length); + eqCount = 0; + while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { + ++eqCount; + } + return eqCount; +}; - __reloader.Reloader = Reloader = (function() { +pathsMatch = function(path1, path2) { + return numberOfMatchingSegments(path1, path2) > 0; +}; - Reloader.name = 'Reloader'; +IMAGE_STYLES = [ + { + selector: 'background', + styleNames: ['backgroundImage'] + }, { + selector: 'border', + styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] + } +]; - function Reloader(window, console, Timer) { - this.window = window; - this.console = console; - this.Timer = Timer; - this.document = this.window.document; - this.importCacheWaitPeriod = 200; - this.plugins = []; - } +__reloader.Reloader = Reloader = (function() { + function Reloader(window, console, Timer) { + this.window = window; + this.console = console; + this.Timer = Timer; + this.document = this.window.document; + this.importCacheWaitPeriod = 200; + this.plugins = []; + } - Reloader.prototype.addPlugin = function(plugin) { - return this.plugins.push(plugin); - }; + Reloader.prototype.addPlugin = function(plugin) { + return this.plugins.push(plugin); + }; - Reloader.prototype.analyze = function(callback) { - return results; - }; + Reloader.prototype.analyze = function(callback) { + return results; + }; - Reloader.prototype.reload = function(path, options) { - var plugin, _base, _i, _len, _ref; - this.options = options; - if ((_base = this.options).stylesheetReloadTimeout == null) { - _base.stylesheetReloadTimeout = 15000; + Reloader.prototype.reload = function(path, options) { + var plugin, _base, _i, _len, _ref; + this.options = options; + if ((_base = this.options).stylesheetReloadTimeout == null) { + _base.stylesheetReloadTimeout = 15000; + } + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + if (plugin.reload && plugin.reload(path, options)) { + return; } - _ref = this.plugins; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - plugin = _ref[_i]; - if (plugin.reload && plugin.reload(path, options)) { + } + if (options.liveCSS) { + if (path.match(/\.css$/i)) { + if (this.reloadStylesheet(path)) { return; } } - if (options.liveCSS) { - if (path.match(/\.css$/i)) { - if (this.reloadStylesheet(path)) { - return; - } - } - } - if (options.liveImg) { - if (path.match(/\.(jpe?g|png|gif)$/i)) { - this.reloadImages(path); - return; - } + } + if (options.liveImg) { + if (path.match(/\.(jpe?g|png|gif)$/i)) { + this.reloadImages(path); + return; } - return this.reloadPage(); - }; + } + return this.reloadPage(); + }; - Reloader.prototype.reloadPage = function() { - return this.window.document.location.reload(); - }; + Reloader.prototype.reloadPage = function() { + return this.window.document.location.reload(); + }; - Reloader.prototype.reloadImages = function(path) { - var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; - expando = this.generateUniqueString(); - _ref = this.document.images; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - img = _ref[_i]; - if (pathsMatch(path, pathFromUrl(img.src))) { - img.src = this.generateCacheBustUrl(img.src, expando); - } + Reloader.prototype.reloadImages = function(path) { + var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; + expando = this.generateUniqueString(); + _ref = this.document.images; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + if (pathsMatch(path, pathFromUrl(img.src))) { + img.src = this.generateCacheBustUrl(img.src, expando); } - if (this.document.querySelectorAll) { - for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { - _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; - _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { - img = _ref2[_k]; - this.reloadStyleImages(img.style, styleNames, path, expando); - } + } + if (this.document.querySelectorAll) { + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; + _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + img = _ref2[_k]; + this.reloadStyleImages(img.style, styleNames, path, expando); } } - if (this.document.styleSheets) { - _ref3 = this.document.styleSheets; - _results = []; - for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { - styleSheet = _ref3[_l]; - _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); - } - return _results; + } + if (this.document.styleSheets) { + _ref3 = this.document.styleSheets; + _results = []; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + styleSheet = _ref3[_l]; + _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); } - }; - - Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { - var rule, rules, styleNames, _i, _j, _len, _len1; - try { - rules = styleSheet != null ? styleSheet.cssRules : void 0; - } catch (e) { + return _results; + } + }; + Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { + var e, rule, rules, styleNames, _i, _j, _len, _len1; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (!rules) { + return; + } + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + switch (rule.type) { + case CSSRule.IMPORT_RULE: + this.reloadStylesheetImages(rule.styleSheet, path, expando); + break; + case CSSRule.STYLE_RULE: + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + styleNames = IMAGE_STYLES[_j].styleNames; + this.reloadStyleImages(rule.style, styleNames, path, expando); + } + break; + case CSSRule.MEDIA_RULE: + this.reloadStylesheetImages(rule, path, expando); } - if (!rules) { - return; - } - for (_i = 0, _len = rules.length; _i < _len; _i++) { - rule = rules[_i]; - switch (rule.type) { - case CSSRule.IMPORT_RULE: - this.reloadStylesheetImages(rule.styleSheet, path, expando); - break; - case CSSRule.STYLE_RULE: - for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { - styleNames = IMAGE_STYLES[_j].styleNames; - this.reloadStyleImages(rule.style, styleNames, path, expando); - } - break; - case CSSRule.MEDIA_RULE: - this.reloadStylesheetImages(rule, path, expando); - } - } - }; + } + }; - Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { - var newValue, styleName, value, _i, _len, - _this = this; - for (_i = 0, _len = styleNames.length; _i < _len; _i++) { - styleName = styleNames[_i]; - value = style[styleName]; - if (typeof value === 'string') { - newValue = value.replace(/\burl\s*\(([^)]*)\)/, function(match, src) { - if (pathsMatch(path, pathFromUrl(src))) { - return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; - } else { - return match; - } - }); - if (newValue !== value) { - style[styleName] = newValue; + Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { + var newValue, styleName, value, _i, _len, + _this = this; + for (_i = 0, _len = styleNames.length; _i < _len; _i++) { + styleName = styleNames[_i]; + value = style[styleName]; + if (typeof value === 'string') { + newValue = value.replace(/\burl\s*\(([^)]*)\)/, function(match, src) { + if (pathsMatch(path, pathFromUrl(src))) { + return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; + } else { + return match; } + }); + if (newValue !== value) { + style[styleName] = newValue; } } - }; + } + }; - Reloader.prototype.reloadStylesheet = function(path) { - var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, - _this = this; - links = (function() { - var _i, _len, _ref, _results; - _ref = this.document.getElementsByTagName('link'); - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) { - _results.push(link); - } - } - return _results; - }).call(this); - imported = []; - _ref = this.document.getElementsByTagName('style'); + Reloader.prototype.reloadStylesheet = function(path) { + var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, + _this = this; + links = (function() { + var _i, _len, _ref, _results; + _ref = this.document.getElementsByTagName('link'); + _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { - style = _ref[_i]; - if (style.sheet) { - this.collectImportedStylesheets(style, style.sheet, imported); + link = _ref[_i]; + if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) { + _results.push(link); } } - for (_j = 0, _len1 = links.length; _j < _len1; _j++) { - link = links[_j]; - this.collectImportedStylesheets(link, link.sheet, imported); + return _results; + }).call(this); + imported = []; + _ref = this.document.getElementsByTagName('style'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + style = _ref[_i]; + if (style.sheet) { + this.collectImportedStylesheets(style, style.sheet, imported); } - if (this.window.StyleFix && this.document.querySelectorAll) { - _ref1 = this.document.querySelectorAll('style[data-href]'); - for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { - style = _ref1[_k]; - links.push(style); - } + } + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + this.collectImportedStylesheets(link, link.sheet, imported); + } + if (this.window.StyleFix && this.document.querySelectorAll) { + _ref1 = this.document.querySelectorAll('style[data-href]'); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + style = _ref1[_k]; + links.push(style); } - this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); - match = pickBestMatch(path, links.concat(imported), function(l) { - return pathFromUrl(_this.linkHref(l)); - }); - if (match) { - if (match.object.rule) { - this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); - this.reattachImportedRule(match.object); - } else { - this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); - this.reattachStylesheetLink(match.object); - } + } + this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); + match = pickBestMatch(path, links.concat(imported), function(l) { + return pathFromUrl(_this.linkHref(l)); + }); + if (match) { + if (match.object.rule) { + this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); + this.reattachImportedRule(match.object); } else { - this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); - for (_l = 0, _len3 = links.length; _l < _len3; _l++) { - link = links[_l]; - this.reattachStylesheetLink(link); - } + this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); + this.reattachStylesheetLink(match.object); } - return true; - }; - - Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { - var index, rule, rules, _i, _len; - try { - rules = styleSheet != null ? styleSheet.cssRules : void 0; - } catch (e) { - + } else { + this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); + for (_l = 0, _len3 = links.length; _l < _len3; _l++) { + link = links[_l]; + this.reattachStylesheetLink(link); } - if (rules && rules.length) { - for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { - rule = rules[index]; - switch (rule.type) { - case CSSRule.CHARSET_RULE: - continue; - case CSSRule.IMPORT_RULE: - result.push({ - link: link, - rule: rule, - index: index, - href: rule.href - }); - this.collectImportedStylesheets(link, rule.styleSheet, result); - break; - default: - break; - } + } + return true; + }; + + Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { + var e, index, rule, rules, _i, _len; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (rules && rules.length) { + for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { + rule = rules[index]; + switch (rule.type) { + case CSSRule.CHARSET_RULE: + continue; + case CSSRule.IMPORT_RULE: + result.push({ + link: link, + rule: rule, + index: index, + href: rule.href + }); + this.collectImportedStylesheets(link, rule.styleSheet, result); + break; + default: + break; } } - }; + } + }; - Reloader.prototype.waitUntilCssLoads = function(clone, func) { - var callbackExecuted, executeCallback, poll, - _this = this; - callbackExecuted = false; - executeCallback = function() { - if (callbackExecuted) { - return; - } - callbackExecuted = true; - return func(); - }; - clone.onload = function() { - console.log("onload!"); - _this.knownToSupportCssOnLoad = true; - return executeCallback(); - }; - if (!this.knownToSupportCssOnLoad) { - (poll = function() { - if (clone.sheet) { - console.log("polling!"); - return executeCallback(); - } else { - return _this.Timer.start(50, poll); - } - })(); + Reloader.prototype.waitUntilCssLoads = function(clone, func) { + var callbackExecuted, executeCallback, poll, + _this = this; + callbackExecuted = false; + executeCallback = function() { + if (callbackExecuted) { + return; } - return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + callbackExecuted = true; + return func(); }; - - Reloader.prototype.linkHref = function(link) { - return link.href || link.getAttribute('data-href'); + clone.onload = function() { + console.log("onload!"); + _this.knownToSupportCssOnLoad = true; + return executeCallback(); }; + if (!this.knownToSupportCssOnLoad) { + (poll = function() { + if (clone.sheet) { + console.log("polling!"); + return executeCallback(); + } else { + return _this.Timer.start(50, poll); + } + })(); + } + return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + }; - Reloader.prototype.reattachStylesheetLink = function(link) { - var clone, parent, - _this = this; - if (link.__LiveReload_pendingRemoval) { - return; - } - link.__LiveReload_pendingRemoval = true; - if (link.tagName === 'STYLE') { - clone = this.document.createElement('link'); - clone.rel = 'stylesheet'; - clone.media = link.media; - clone.disabled = link.disabled; - } else { - clone = link.cloneNode(false); - } - clone.href = this.generateCacheBustUrl(this.linkHref(link)); - parent = link.parentNode; - if (parent.lastChild === link) { - parent.appendChild(clone); + Reloader.prototype.linkHref = function(link) { + return link.href || link.getAttribute('data-href'); + }; + + Reloader.prototype.reattachStylesheetLink = function(link) { + var clone, parent, + _this = this; + if (link.__LiveReload_pendingRemoval) { + return; + } + link.__LiveReload_pendingRemoval = true; + if (link.tagName === 'STYLE') { + clone = this.document.createElement('link'); + clone.rel = 'stylesheet'; + clone.media = link.media; + clone.disabled = link.disabled; + } else { + clone = link.cloneNode(false); + } + clone.href = this.generateCacheBustUrl(this.linkHref(link)); + parent = link.parentNode; + if (parent.lastChild === link) { + parent.appendChild(clone); + } else { + parent.insertBefore(clone, link.nextSibling); + } + return this.waitUntilCssLoads(clone, function() { + var additionalWaitingTime; + if (/AppleWebKit/.test(navigator.userAgent)) { + additionalWaitingTime = 5; } else { - parent.insertBefore(clone, link.nextSibling); + additionalWaitingTime = 200; } - return this.waitUntilCssLoads(clone, function() { - var additionalWaitingTime; - if (/AppleWebKit/.test(navigator.userAgent)) { - additionalWaitingTime = 5; - } else { - additionalWaitingTime = 200; + return _this.Timer.start(additionalWaitingTime, function() { + var _ref; + if (!link.parentNode) { + return; } - return _this.Timer.start(additionalWaitingTime, function() { - var _ref; - if (!link.parentNode) { - return; - } - link.parentNode.removeChild(link); - clone.onreadystatechange = null; - return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; - }); + link.parentNode.removeChild(link); + clone.onreadystatechange = null; + return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; }); - }; + }); + }; - Reloader.prototype.reattachImportedRule = function(_arg) { - var href, index, link, media, newRule, parent, rule, tempLink, - _this = this; - rule = _arg.rule, index = _arg.index, link = _arg.link; - parent = rule.parentStyleSheet; - href = this.generateCacheBustUrl(rule.href); - media = rule.media.length ? [].join.call(rule.media, ', ') : ''; - newRule = "@import url(\"" + href + "\") " + media + ";"; - rule.__LiveReload_newHref = href; - tempLink = this.document.createElement("link"); - tempLink.rel = 'stylesheet'; - tempLink.href = href; - tempLink.__LiveReload_pendingRemoval = true; - if (link.parentNode) { - link.parentNode.insertBefore(tempLink, link); + Reloader.prototype.reattachImportedRule = function(_arg) { + var href, index, link, media, newRule, parent, rule, tempLink, + _this = this; + rule = _arg.rule, index = _arg.index, link = _arg.link; + parent = rule.parentStyleSheet; + href = this.generateCacheBustUrl(rule.href); + media = rule.media.length ? [].join.call(rule.media, ', ') : ''; + newRule = "@import url(\"" + href + "\") " + media + ";"; + rule.__LiveReload_newHref = href; + tempLink = this.document.createElement("link"); + tempLink.rel = 'stylesheet'; + tempLink.href = href; + tempLink.__LiveReload_pendingRemoval = true; + if (link.parentNode) { + link.parentNode.insertBefore(tempLink, link); + } + return this.Timer.start(this.importCacheWaitPeriod, function() { + if (tempLink.parentNode) { + tempLink.parentNode.removeChild(tempLink); } - return this.Timer.start(this.importCacheWaitPeriod, function() { - if (tempLink.parentNode) { - tempLink.parentNode.removeChild(tempLink); - } + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + parent.deleteRule(index + 1); + rule = parent.cssRules[index]; + rule.__LiveReload_newHref = href; + return _this.Timer.start(_this.importCacheWaitPeriod, function() { if (rule.__LiveReload_newHref !== href) { return; } parent.insertRule(newRule, index); - parent.deleteRule(index + 1); - rule = parent.cssRules[index]; - rule.__LiveReload_newHref = href; - return _this.Timer.start(_this.importCacheWaitPeriod, function() { - if (rule.__LiveReload_newHref !== href) { - return; - } - parent.insertRule(newRule, index); - return parent.deleteRule(index + 1); - }); + return parent.deleteRule(index + 1); }); - }; + }); + }; - Reloader.prototype.generateUniqueString = function() { - return 'livereload=' + Date.now(); - }; + Reloader.prototype.generateUniqueString = function() { + return 'livereload=' + Date.now(); + }; - Reloader.prototype.generateCacheBustUrl = function(url, expando) { - var hash, oldParams, params, _ref; - if (expando == null) { - expando = this.generateUniqueString(); - } - _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; - if (this.options.overrideURL) { - if (url.indexOf(this.options.serverURL) < 0) { - url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); - } + Reloader.prototype.generateCacheBustUrl = function(url, expando) { + var hash, oldParams, params, _ref; + if (expando == null) { + expando = this.generateUniqueString(); + } + _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; + if (this.options.overrideURL) { + if (url.indexOf(this.options.serverURL) < 0) { + url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); } - params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { - return "" + sep + expando; - }); - if (params === oldParams) { - if (oldParams.length === 0) { - params = "?" + expando; - } else { - params = "" + oldParams + "&" + expando; - } + } + params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { + return "" + sep + expando; + }); + if (params === oldParams) { + if (oldParams.length === 0) { + params = "?" + expando; + } else { + params = "" + oldParams + "&" + expando; } - return url + params + hash; - }; - - return Reloader; + } + return url + params + hash; + }; - })(); + return Reloader; -}).call(this); +})(); // livereload +// Generated by CoffeeScript 1.6.3 var Connector, LiveReload, Options, Reloader, Timer; Connector = __connector.Connector; @@ -831,7 +914,6 @@ Options = __options.Options; Reloader = __reloader.Reloader; __livereload.LiveReload = LiveReload = (function() { - function LiveReload(window) { var _this = this; this.window = window; @@ -911,15 +993,16 @@ __livereload.LiveReload = LiveReload = (function() { }; LiveReload.prototype.performReload = function(message) { - var _ref, _ref2; + var _base, _ref, _ref1; this.log("LiveReload received reload request for " + message.path + "."); - return this.reloader.reload(message.path, { + this.reloader.reload(message.path, { liveCSS: (_ref = message.liveCSS) != null ? _ref : true, - liveImg: (_ref2 = message.liveImg) != null ? _ref2 : true, + liveImg: (_ref1 = message.liveImg) != null ? _ref1 : true, originalPath: message.originalPath || '', overrideURL: message.overrideURL || '', serverURL: "http://" + this.options.host + ":" + this.options.port }); + return typeof (_base = this.listeners).reload === "function" ? _base.reload() : void 0; }; LiveReload.prototype.performAlert = function(message) { @@ -938,9 +1021,11 @@ __livereload.LiveReload = LiveReload = (function() { }; LiveReload.prototype.addPlugin = function(pluginClass) { - var plugin; - var _this = this; - if (this.hasPlugin(pluginClass.identifier)) return; + var plugin, + _this = this; + if (this.hasPlugin(pluginClass.identifier)) { + return; + } this.pluginIdentifiers[pluginClass.identifier] = true; plugin = new pluginClass(this.window, { _livereload: this, @@ -958,7 +1043,9 @@ __livereload.LiveReload = LiveReload = (function() { LiveReload.prototype.analyze = function() { var plugin, pluginData, pluginsData, _i, _len, _ref; - if (!(this.connector.protocol >= 7)) return; + if (!(this.connector.protocol >= 7)) { + return; + } pluginsData = {}; _ref = this.plugins; for (_i = 0, _len = _ref.length; _i < _len; _i++) { @@ -973,82 +1060,70 @@ __livereload.LiveReload = LiveReload = (function() { }); }; - return LiveReload; - -})(); - -// less -var LessPlugin; -__less = LessPlugin = (function() { - LessPlugin.identifier = 'less'; - LessPlugin.version = '1.0'; - function LessPlugin(window, host) { - this.window = window; - this.host = host; - } - LessPlugin.prototype.reload = function(path, options) { - if (this.window.less && this.window.less.refresh) { - if (path.match(/\.less$/i)) { - return this.reloadLess(path); - } - if (options.originalPath.match(/\.less$/i)) { - return this.reloadLess(options.originalPath); - } - } - return false; - }; - LessPlugin.prototype.reloadLess = function(path) { - var link, links, _i, _len; - links = (function() { - var _i, _len, _ref, _results; - _ref = document.getElementsByTagName('link'); - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link.href && link.rel === 'stylesheet/less' || (link.rel.match(/stylesheet/) && link.type.match(/^text\/(x-)?less$/))) { - _results.push(link); - } - } - return _results; - })(); - if (links.length === 0) { - return false; - } - for (_i = 0, _len = links.length; _i < _len; _i++) { - link = links[_i]; - link.href = this.host.generateCacheBustUrl(link.href); - } - this.host.console.log("LiveReload is asking LESS to recompile all stylesheets"); - this.window.less.refresh(true); - return true; - }; - LessPlugin.prototype.analyze = function() { - return { - disable: !!(this.window.less && this.window.less.refresh) + LiveReload.prototype.setUpCSSTransitions = function() { + var cssText, head, prefixer, styleNode; + prefixer = function(declaration) { + return (['-webkit-', '-moz-', ''].map(function(item) { + return "" + item + declaration; + })).join(' '); }; + head = document.getElementsByTagName('head')[0]; + styleNode = document.createElement("style"); + cssText = ".livereload-reloaded * { " + (prefixer('transition: all 280ms ease-out;')) + " }"; + if (styleNode.styleSheet) { + styleNode.styleSheet.cssText = cssText; + } else { + styleNode.appendChild(document.createTextNode(cssText)); + } + return head.appendChild(styleNode); }; - return LessPlugin; + + return LiveReload; + })(); // startup +// Generated by CoffeeScript 1.6.3 var CustomEvents, LiveReload, k; + CustomEvents = __customevents; + LiveReload = window.LiveReload = new (__livereload.LiveReload)(window); + for (k in window) { if (k.match(/^LiveReloadPlugin/)) { LiveReload.addPlugin(window[k]); } } + LiveReload.addPlugin(__less); + LiveReload.on('shutdown', function() { return delete window.LiveReload; }); + LiveReload.on('connect', function() { + if (!!/true|1$/.test(LiveReload.options.animate)) { + LiveReload.setUpCSSTransitions(); + } return CustomEvents.fire(document, 'LiveReloadConnect'); }); + LiveReload.on('disconnect', function() { return CustomEvents.fire(document, 'LiveReloadDisconnect'); }); + +LiveReload.on('reload', function() { + var existingHtmlClass, html, reloadedClass, _ref; + html = document.body.parentNode; + reloadedClass = ' livereload-reloaded'; + existingHtmlClass = (_ref = html.getAttribute('class')) != null ? _ref : ''; + html.setAttribute('class', "" + (existingHtmlClass.replace(reloadedClass, '')) + " " + reloadedClass); + return setTimeout((function() { + return html.setAttribute('class', existingHtmlClass.replace(reloadedClass, '')); + }), 300); +}); + CustomEvents.bind(document, 'LiveReloadShutDown', function() { return LiveReload.shutDown(); }); diff --git a/src/connector.coffee b/src/connector.coffee index 5c102a0..1ec0fe6 100644 --- a/src/connector.coffee +++ b/src/connector.coffee @@ -1,6 +1,6 @@ { Parser, PROTOCOL_6, PROTOCOL_7 } = require 'protocol' -Version = '2.0.8' +Version = '2.0.9' exports.Connector = class Connector diff --git a/src/livereload.coffee b/src/livereload.coffee index d4618b3..c929b5d 100644 --- a/src/livereload.coffee +++ b/src/livereload.coffee @@ -82,6 +82,7 @@ exports.LiveReload = class LiveReload originalPath: message.originalPath || '' overrideURL: message.overrideURL || '' serverURL: "http://#{@options.host}:#{@options.port}" + @listeners.reload?() performAlert: (message) -> alert message.message @@ -143,3 +144,18 @@ exports.LiveReload = class LiveReload @connector.sendCommand { command: 'info', plugins: pluginsData, url: @window.location.href } return + + setUpCSSTransitions: -> + prefixer = (declaration) -> + (['-webkit-', '-moz-', ''].map (item) -> ("#{item}#{declaration}")).join(' ') + + head = document.getElementsByTagName('head')[0]; + styleNode = document.createElement("style"); + cssText = ".livereload-reloaded * { #{prefixer('transition: all 280ms ease-out;')} }"; + + if styleNode.styleSheet + styleNode.styleSheet.cssText = cssText; + else + styleNode.appendChild(document.createTextNode(cssText)) + + head.appendChild(styleNode) diff --git a/src/options.coffee b/src/options.coffee index 5d9befa..a75f8bf 100644 --- a/src/options.coffee +++ b/src/options.coffee @@ -12,6 +12,8 @@ exports.Options = class Options @maxdelay = 60000 @handshake_timeout = 5000 + @animate = false + set: (name, value) -> switch typeof @[name] when 'undefined' then # ignore diff --git a/src/startup.coffee b/src/startup.coffee index ff3446a..86735aa 100644 --- a/src/startup.coffee +++ b/src/startup.coffee @@ -8,8 +8,16 @@ LiveReload.addPlugin require('less') LiveReload.on 'shutdown', -> delete window.LiveReload LiveReload.on 'connect', -> + LiveReload.setUpCSSTransitions() if !!(/true|1$/).test(LiveReload.options.animate) CustomEvents.fire document, 'LiveReloadConnect' LiveReload.on 'disconnect', -> CustomEvents.fire document, 'LiveReloadDisconnect' +LiveReload.on 'reload', -> + html = document.body.parentNode + reloadedClass = ' livereload-reloaded' + existingHtmlClass = html.getAttribute('class') ? '' + html.setAttribute('class', "#{existingHtmlClass.replace(reloadedClass, '')} #{reloadedClass}") + setTimeout (-> html.setAttribute('class', existingHtmlClass.replace(reloadedClass, ''))), 300 + CustomEvents.bind document, 'LiveReloadShutDown', -> LiveReload.shutDown()