rack-livereload 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/js/livereload.js +843 -721
- data/lib/rack-livereload.rb +1 -1
- data/lib/rack/livereload.rb +1 -1
- data/spec/rack/livereload_spec.rb +8 -0
- metadata +32 -26
data/js/livereload.js
CHANGED
@@ -1,804 +1,926 @@
|
|
1
1
|
(function() {
|
2
|
-
var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __startup = {};
|
2
|
+
var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __less = {}, __startup = {};
|
3
3
|
|
4
4
|
// customevents
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
return handler();
|
16
|
-
}
|
17
|
-
});
|
18
|
-
} else {
|
19
|
-
throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement");
|
20
|
-
}
|
21
|
-
},
|
22
|
-
fire: function(element, eventName) {
|
23
|
-
var event;
|
24
|
-
if (element.addEventListener) {
|
25
|
-
event = document.createEvent('HTMLEvents');
|
26
|
-
event.initEvent(eventName, true, true);
|
27
|
-
return document.dispatchEvent(event);
|
28
|
-
} else if (element.attachEvent) {
|
29
|
-
if (element[eventName]) {
|
30
|
-
return element[eventName]++;
|
5
|
+
var CustomEvents;
|
6
|
+
CustomEvents = {
|
7
|
+
bind: function(element, eventName, handler) {
|
8
|
+
if (element.addEventListener) {
|
9
|
+
return element.addEventListener(eventName, handler, false);
|
10
|
+
} else if (element.attachEvent) {
|
11
|
+
element[eventName] = 1;
|
12
|
+
return element.attachEvent('onpropertychange', function(event) {
|
13
|
+
if (event.propertyName === eventName) {
|
14
|
+
return handler();
|
31
15
|
}
|
32
|
-
}
|
33
|
-
|
16
|
+
});
|
17
|
+
} else {
|
18
|
+
throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement");
|
19
|
+
}
|
20
|
+
},
|
21
|
+
fire: function(element, eventName) {
|
22
|
+
var event;
|
23
|
+
if (element.addEventListener) {
|
24
|
+
event = document.createEvent('HTMLEvents');
|
25
|
+
event.initEvent(eventName, true, true);
|
26
|
+
return document.dispatchEvent(event);
|
27
|
+
} else if (element.attachEvent) {
|
28
|
+
if (element[eventName]) {
|
29
|
+
return element[eventName]++;
|
34
30
|
}
|
31
|
+
} else {
|
32
|
+
throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement");
|
35
33
|
}
|
36
|
-
}
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
}
|
35
|
+
};
|
36
|
+
__customevents.bind = CustomEvents.bind;
|
37
|
+
__customevents.fire = CustomEvents.fire;
|
40
38
|
|
41
39
|
// protocol
|
42
|
-
|
43
|
-
|
44
|
-
var
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
if (
|
70
|
-
|
40
|
+
var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError;
|
41
|
+
var __indexOf = Array.prototype.indexOf || function(item) {
|
42
|
+
for (var i = 0, l = this.length; i < l; i++) {
|
43
|
+
if (this[i] === item) return i;
|
44
|
+
}
|
45
|
+
return -1;
|
46
|
+
};
|
47
|
+
__protocol.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6';
|
48
|
+
__protocol.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7';
|
49
|
+
__protocol.ProtocolError = ProtocolError = (function() {
|
50
|
+
function ProtocolError(reason, data) {
|
51
|
+
this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\".";
|
52
|
+
}
|
53
|
+
return ProtocolError;
|
54
|
+
})();
|
55
|
+
__protocol.Parser = Parser = (function() {
|
56
|
+
function Parser(handlers) {
|
57
|
+
this.handlers = handlers;
|
58
|
+
this.reset();
|
59
|
+
}
|
60
|
+
Parser.prototype.reset = function() {
|
61
|
+
return this.protocol = null;
|
62
|
+
};
|
63
|
+
Parser.prototype.process = function(data) {
|
64
|
+
var command, message, options, _ref;
|
65
|
+
try {
|
66
|
+
if (!(this.protocol != null)) {
|
67
|
+
if (data.match(/^!!ver:([\d.]+)$/)) {
|
68
|
+
this.protocol = 6;
|
69
|
+
} else if (message = this._parseMessage(data, ['hello'])) {
|
70
|
+
if (!message.protocols.length) {
|
71
|
+
throw new ProtocolError("no protocols specified in handshake message");
|
72
|
+
} else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) {
|
73
|
+
this.protocol = 7;
|
74
|
+
} else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) {
|
71
75
|
this.protocol = 6;
|
72
|
-
} else
|
73
|
-
|
74
|
-
throw new ProtocolError("no protocols specified in handshake message");
|
75
|
-
} else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) {
|
76
|
-
this.protocol = 7;
|
77
|
-
} else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) {
|
78
|
-
this.protocol = 6;
|
79
|
-
} else {
|
80
|
-
throw new ProtocolError("no supported protocols found");
|
81
|
-
}
|
82
|
-
}
|
83
|
-
return this.handlers.connected(this.protocol);
|
84
|
-
} else if (this.protocol === 6) {
|
85
|
-
message = JSON.parse(data);
|
86
|
-
if (!message.length) {
|
87
|
-
throw new ProtocolError("protocol 6 messages must be arrays");
|
88
|
-
}
|
89
|
-
command = message[0], options = message[1];
|
90
|
-
if (command !== 'refresh') {
|
91
|
-
throw new ProtocolError("unknown protocol 6 command");
|
76
|
+
} else {
|
77
|
+
throw new ProtocolError("no supported protocols found");
|
92
78
|
}
|
93
|
-
return this.handlers.message({
|
94
|
-
command: 'reload',
|
95
|
-
path: options.path,
|
96
|
-
liveCSS: (_ref = options.apply_css_live) != null ? _ref : true
|
97
|
-
});
|
98
|
-
} else {
|
99
|
-
message = this._parseMessage(data, ['reload', 'alert']);
|
100
|
-
return this.handlers.message(message);
|
101
|
-
}
|
102
|
-
} catch (e) {
|
103
|
-
if (e instanceof ProtocolError) {
|
104
|
-
return this.handlers.error(e);
|
105
|
-
} else {
|
106
|
-
throw e;
|
107
79
|
}
|
108
|
-
|
109
|
-
|
110
|
-
Parser.prototype._parseMessage = function(data, validCommands) {
|
111
|
-
var message, _ref;
|
112
|
-
try {
|
80
|
+
return this.handlers.connected(this.protocol);
|
81
|
+
} else if (this.protocol === 6) {
|
113
82
|
message = JSON.parse(data);
|
114
|
-
|
115
|
-
|
116
|
-
}
|
117
|
-
if (!message.command) {
|
118
|
-
throw new ProtocolError('missing "command" key', data);
|
119
|
-
}
|
120
|
-
if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) {
|
121
|
-
throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data);
|
122
|
-
}
|
123
|
-
return message;
|
124
|
-
};
|
125
|
-
return Parser;
|
126
|
-
})();
|
127
|
-
}).call(this);
|
128
|
-
|
129
|
-
// connector
|
130
|
-
(function() {
|
131
|
-
var Connector, PROTOCOL_6, PROTOCOL_7, Parser, _ref;
|
132
|
-
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
133
|
-
_ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7;
|
134
|
-
__connector.Connector = Connector = (function() {
|
135
|
-
function Connector(options, WebSocket, Timer, handlers) {
|
136
|
-
this.options = options;
|
137
|
-
this.WebSocket = WebSocket;
|
138
|
-
this.Timer = Timer;
|
139
|
-
this.handlers = handlers;
|
140
|
-
this._uri = "ws://" + this.options.host + ":" + this.options.port + "/livereload";
|
141
|
-
this._nextDelay = this.options.mindelay;
|
142
|
-
this._connectionDesired = false;
|
143
|
-
this.protocolParser = new Parser({
|
144
|
-
connected: __bind(function(protocol) {
|
145
|
-
this._handshakeTimeout.stop();
|
146
|
-
this._nextDelay = this.options.mindelay;
|
147
|
-
this._disconnectionReason = 'broken';
|
148
|
-
return this.handlers.connected(protocol);
|
149
|
-
}, this),
|
150
|
-
error: __bind(function(e) {
|
151
|
-
this.handlers.error(e);
|
152
|
-
return this._closeOnError();
|
153
|
-
}, this),
|
154
|
-
message: __bind(function(message) {
|
155
|
-
return this.handlers.message(message);
|
156
|
-
}, this)
|
157
|
-
});
|
158
|
-
this._handshakeTimeout = new Timer(__bind(function() {
|
159
|
-
if (!this._isSocketConnected()) {
|
160
|
-
return;
|
83
|
+
if (!message.length) {
|
84
|
+
throw new ProtocolError("protocol 6 messages must be arrays");
|
161
85
|
}
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
this._reconnectTimer = new Timer(__bind(function() {
|
166
|
-
if (!this._connectionDesired) {
|
167
|
-
return;
|
86
|
+
command = message[0], options = message[1];
|
87
|
+
if (command !== 'refresh') {
|
88
|
+
throw new ProtocolError("unknown protocol 6 command");
|
168
89
|
}
|
169
|
-
return this.
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
this._connectionDesired = true;
|
178
|
-
if (this._isSocketConnected()) {
|
179
|
-
return;
|
90
|
+
return this.handlers.message({
|
91
|
+
command: 'reload',
|
92
|
+
path: options.path,
|
93
|
+
liveCSS: (_ref = options.apply_css_live) != null ? _ref : true
|
94
|
+
});
|
95
|
+
} else {
|
96
|
+
message = this._parseMessage(data, ['reload', 'alert']);
|
97
|
+
return this.handlers.message(message);
|
180
98
|
}
|
181
|
-
|
182
|
-
|
99
|
+
} catch (e) {
|
100
|
+
if (e instanceof ProtocolError) {
|
101
|
+
return this.handlers.error(e);
|
102
|
+
} else {
|
103
|
+
throw e;
|
183
104
|
}
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
105
|
+
}
|
106
|
+
};
|
107
|
+
Parser.prototype._parseMessage = function(data, validCommands) {
|
108
|
+
var message, _ref;
|
109
|
+
try {
|
110
|
+
message = JSON.parse(data);
|
111
|
+
} catch (e) {
|
112
|
+
throw new ProtocolError('unparsable JSON', data);
|
113
|
+
}
|
114
|
+
if (!message.command) {
|
115
|
+
throw new ProtocolError('missing "command" key', data);
|
116
|
+
}
|
117
|
+
if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) {
|
118
|
+
throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data);
|
119
|
+
}
|
120
|
+
return message;
|
121
|
+
};
|
122
|
+
return Parser;
|
123
|
+
})();
|
124
|
+
|
125
|
+
// connector
|
126
|
+
var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref;
|
127
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
128
|
+
_ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7;
|
129
|
+
Version = '2.0.3';
|
130
|
+
__connector.Connector = Connector = (function() {
|
131
|
+
function Connector(options, WebSocket, Timer, handlers) {
|
132
|
+
this.options = options;
|
133
|
+
this.WebSocket = WebSocket;
|
134
|
+
this.Timer = Timer;
|
135
|
+
this.handlers = handlers;
|
136
|
+
this._uri = "ws://" + this.options.host + ":" + this.options.port + "/livereload";
|
137
|
+
this._nextDelay = this.options.mindelay;
|
138
|
+
this._connectionDesired = false;
|
139
|
+
this.protocol = 0;
|
140
|
+
this.protocolParser = new Parser({
|
141
|
+
connected: __bind(function(protocol) {
|
142
|
+
this.protocol = protocol;
|
143
|
+
this._handshakeTimeout.stop();
|
144
|
+
this._nextDelay = this.options.mindelay;
|
145
|
+
this._disconnectionReason = 'broken';
|
146
|
+
return this.handlers.connected(protocol);
|
147
|
+
}, this),
|
148
|
+
error: __bind(function(e) {
|
149
|
+
this.handlers.error(e);
|
150
|
+
return this._closeOnError();
|
151
|
+
}, this),
|
152
|
+
message: __bind(function(message) {
|
153
|
+
return this.handlers.message(message);
|
154
|
+
}, this)
|
155
|
+
});
|
156
|
+
this._handshakeTimeout = new Timer(__bind(function() {
|
204
157
|
if (!this._isSocketConnected()) {
|
205
158
|
return;
|
206
159
|
}
|
207
|
-
this._disconnectionReason = '
|
160
|
+
this._disconnectionReason = 'handshake-timeout';
|
208
161
|
return this.socket.close();
|
209
|
-
};
|
210
|
-
|
162
|
+
}, this));
|
163
|
+
this._reconnectTimer = new Timer(__bind(function() {
|
211
164
|
if (!this._connectionDesired) {
|
212
165
|
return;
|
213
166
|
}
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
this.
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
return this.
|
241
|
-
};
|
242
|
-
|
243
|
-
this.
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
167
|
+
return this.connect();
|
168
|
+
}, this));
|
169
|
+
this.connect();
|
170
|
+
}
|
171
|
+
Connector.prototype._isSocketConnected = function() {
|
172
|
+
return this.socket && this.socket.readyState === this.WebSocket.OPEN;
|
173
|
+
};
|
174
|
+
Connector.prototype.connect = function() {
|
175
|
+
this._connectionDesired = true;
|
176
|
+
if (this._isSocketConnected()) {
|
177
|
+
return;
|
178
|
+
}
|
179
|
+
if (this._reconnectTimer) {
|
180
|
+
clearTimeout(this._reconnectTimer);
|
181
|
+
}
|
182
|
+
this._disconnectionReason = 'cannot-connect';
|
183
|
+
this.protocolParser.reset();
|
184
|
+
this.handlers.connecting();
|
185
|
+
this.socket = new this.WebSocket(this._uri);
|
186
|
+
this.socket.onopen = __bind(function(e) {
|
187
|
+
return this._onopen(e);
|
188
|
+
}, this);
|
189
|
+
this.socket.onclose = __bind(function(e) {
|
190
|
+
return this._onclose(e);
|
191
|
+
}, this);
|
192
|
+
this.socket.onmessage = __bind(function(e) {
|
193
|
+
return this._onmessage(e);
|
194
|
+
}, this);
|
195
|
+
return this.socket.onerror = __bind(function(e) {
|
196
|
+
return this._onerror(e);
|
197
|
+
}, this);
|
198
|
+
};
|
199
|
+
Connector.prototype.disconnect = function() {
|
200
|
+
this._connectionDesired = false;
|
201
|
+
this._reconnectTimer.stop();
|
202
|
+
if (!this._isSocketConnected()) {
|
203
|
+
return;
|
204
|
+
}
|
205
|
+
this._disconnectionReason = 'manual';
|
206
|
+
return this.socket.close();
|
207
|
+
};
|
208
|
+
Connector.prototype._scheduleReconnection = function() {
|
209
|
+
if (!this._connectionDesired) {
|
210
|
+
return;
|
211
|
+
}
|
212
|
+
if (!this._reconnectTimer.running) {
|
213
|
+
this._reconnectTimer.start(this._nextDelay);
|
214
|
+
return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2);
|
215
|
+
}
|
216
|
+
};
|
217
|
+
Connector.prototype.sendCommand = function(command) {
|
218
|
+
if (this.protocol == null) {
|
219
|
+
return;
|
220
|
+
}
|
221
|
+
return this._sendCommand(command);
|
222
|
+
};
|
223
|
+
Connector.prototype._sendCommand = function(command) {
|
224
|
+
return this.socket.send(JSON.stringify(command));
|
225
|
+
};
|
226
|
+
Connector.prototype._closeOnError = function() {
|
227
|
+
this._handshakeTimeout.stop();
|
228
|
+
this._disconnectionReason = 'error';
|
229
|
+
return this.socket.close();
|
230
|
+
};
|
231
|
+
Connector.prototype._onopen = function(e) {
|
232
|
+
var hello;
|
233
|
+
this.handlers.socketConnected();
|
234
|
+
this._disconnectionReason = 'handshake-failed';
|
235
|
+
hello = {
|
236
|
+
command: 'hello',
|
237
|
+
protocols: [PROTOCOL_6, PROTOCOL_7]
|
238
|
+
};
|
239
|
+
hello.ver = Version;
|
240
|
+
if (this.options.ext) {
|
241
|
+
hello.ext = this.options.ext;
|
242
|
+
}
|
243
|
+
if (this.options.extver) {
|
244
|
+
hello.extver = this.options.extver;
|
245
|
+
}
|
246
|
+
if (this.options.snipver) {
|
247
|
+
hello.snipver = this.options.snipver;
|
248
|
+
}
|
249
|
+
this._sendCommand(hello);
|
250
|
+
return this._handshakeTimeout.start(this.options.handshake_timeout);
|
251
|
+
};
|
252
|
+
Connector.prototype._onclose = function(e) {
|
253
|
+
this.protocol = 0;
|
254
|
+
this.handlers.disconnected(this._disconnectionReason, this._nextDelay);
|
255
|
+
return this._scheduleReconnection();
|
256
|
+
};
|
257
|
+
Connector.prototype._onerror = function(e) {};
|
258
|
+
Connector.prototype._onmessage = function(e) {
|
259
|
+
return this.protocolParser.process(e.data);
|
260
|
+
};
|
261
|
+
return Connector;
|
262
|
+
})();
|
253
263
|
|
254
264
|
// timer
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
265
|
+
var Timer;
|
266
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
267
|
+
__timer.Timer = Timer = (function() {
|
268
|
+
function Timer(func) {
|
269
|
+
this.func = func;
|
270
|
+
this.running = false;
|
271
|
+
this.id = null;
|
272
|
+
this._handler = __bind(function() {
|
261
273
|
this.running = false;
|
262
274
|
this.id = null;
|
263
|
-
this.
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
this.running = false;
|
280
|
-
return this.id = null;
|
281
|
-
}
|
282
|
-
};
|
283
|
-
return Timer;
|
284
|
-
})();
|
285
|
-
Timer.start = function(timeout, func) {
|
286
|
-
return setTimeout(func, timeout);
|
275
|
+
return this.func();
|
276
|
+
}, this);
|
277
|
+
}
|
278
|
+
Timer.prototype.start = function(timeout) {
|
279
|
+
if (this.running) {
|
280
|
+
clearTimeout(this.id);
|
281
|
+
}
|
282
|
+
this.id = setTimeout(this._handler, timeout);
|
283
|
+
return this.running = true;
|
284
|
+
};
|
285
|
+
Timer.prototype.stop = function() {
|
286
|
+
if (this.running) {
|
287
|
+
clearTimeout(this.id);
|
288
|
+
this.running = false;
|
289
|
+
return this.id = null;
|
290
|
+
}
|
287
291
|
};
|
288
|
-
|
292
|
+
return Timer;
|
293
|
+
})();
|
294
|
+
Timer.start = function(timeout, func) {
|
295
|
+
return setTimeout(func, timeout);
|
296
|
+
};
|
289
297
|
|
290
298
|
// options
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
options.port = parseInt(mm[2], 10);
|
327
|
-
}
|
299
|
+
var Options;
|
300
|
+
__options.Options = Options = (function() {
|
301
|
+
function Options() {
|
302
|
+
this.host = null;
|
303
|
+
this.port = 35729;
|
304
|
+
this.snipver = null;
|
305
|
+
this.ext = null;
|
306
|
+
this.extver = null;
|
307
|
+
this.mindelay = 1000;
|
308
|
+
this.maxdelay = 60000;
|
309
|
+
this.handshake_timeout = 5000;
|
310
|
+
}
|
311
|
+
Options.prototype.set = function(name, value) {
|
312
|
+
switch (typeof this[name]) {
|
313
|
+
case 'undefined':
|
314
|
+
break;
|
315
|
+
case 'number':
|
316
|
+
return this[name] = +value;
|
317
|
+
default:
|
318
|
+
return this[name] = value;
|
319
|
+
}
|
320
|
+
};
|
321
|
+
return Options;
|
322
|
+
})();
|
323
|
+
Options.extract = function(document) {
|
324
|
+
var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len2, _ref, _ref2;
|
325
|
+
_ref = document.getElementsByTagName('script');
|
326
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
327
|
+
element = _ref[_i];
|
328
|
+
if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) {
|
329
|
+
options = new Options();
|
330
|
+
if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) {
|
331
|
+
options.host = mm[1];
|
332
|
+
if (mm[2]) {
|
333
|
+
options.port = parseInt(mm[2], 10);
|
328
334
|
}
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
335
|
+
}
|
336
|
+
if (m[2]) {
|
337
|
+
_ref2 = m[2].split('&');
|
338
|
+
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
|
339
|
+
pair = _ref2[_j];
|
340
|
+
if ((keyAndValue = pair.split('=')).length > 1) {
|
341
|
+
options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('='));
|
336
342
|
}
|
337
343
|
}
|
338
|
-
return options;
|
339
344
|
}
|
345
|
+
return options;
|
340
346
|
}
|
341
|
-
|
342
|
-
|
343
|
-
}
|
347
|
+
}
|
348
|
+
return null;
|
349
|
+
};
|
344
350
|
|
345
351
|
// reloader
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
hash: hash
|
367
|
-
};
|
352
|
+
var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl;
|
353
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
354
|
+
splitUrl = function(url) {
|
355
|
+
var hash, index, params;
|
356
|
+
if ((index = url.indexOf('#')) >= 0) {
|
357
|
+
hash = url.slice(index);
|
358
|
+
url = url.slice(0, index);
|
359
|
+
} else {
|
360
|
+
hash = '';
|
361
|
+
}
|
362
|
+
if ((index = url.indexOf('?')) >= 0) {
|
363
|
+
params = url.slice(index);
|
364
|
+
url = url.slice(0, index);
|
365
|
+
} else {
|
366
|
+
params = '';
|
367
|
+
}
|
368
|
+
return {
|
369
|
+
url: url,
|
370
|
+
params: params,
|
371
|
+
hash: hash
|
368
372
|
};
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
373
|
+
};
|
374
|
+
pathFromUrl = function(url) {
|
375
|
+
var path;
|
376
|
+
url = splitUrl(url).url;
|
377
|
+
if (url.indexOf('file://') === 0) {
|
378
|
+
path = url.replace(/^file:\/\/(localhost)?/, '');
|
379
|
+
} else {
|
380
|
+
path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/');
|
381
|
+
}
|
382
|
+
return decodeURIComponent(path);
|
383
|
+
};
|
384
|
+
pickBestMatch = function(path, objects, pathFunc) {
|
385
|
+
var bestMatch, object, score, _i, _len;
|
386
|
+
bestMatch = {
|
387
|
+
score: 0
|
388
|
+
};
|
389
|
+
for (_i = 0, _len = objects.length; _i < _len; _i++) {
|
390
|
+
object = objects[_i];
|
391
|
+
score = numberOfMatchingSegments(path, pathFunc(object));
|
392
|
+
if (score > bestMatch.score) {
|
393
|
+
bestMatch = {
|
394
|
+
object: object,
|
395
|
+
score: score
|
396
|
+
};
|
376
397
|
}
|
377
|
-
|
398
|
+
}
|
399
|
+
if (bestMatch.score > 0) {
|
400
|
+
return bestMatch;
|
401
|
+
} else {
|
402
|
+
return null;
|
403
|
+
}
|
404
|
+
};
|
405
|
+
numberOfMatchingSegments = function(path1, path2) {
|
406
|
+
var comps1, comps2, eqCount, len;
|
407
|
+
path1 = path1.replace(/^\/+/, '').toLowerCase();
|
408
|
+
path2 = path2.replace(/^\/+/, '').toLowerCase();
|
409
|
+
if (path1 === path2) {
|
410
|
+
return 10000;
|
411
|
+
}
|
412
|
+
comps1 = path1.split('/').reverse();
|
413
|
+
comps2 = path2.split('/').reverse();
|
414
|
+
len = Math.min(comps1.length, comps2.length);
|
415
|
+
eqCount = 0;
|
416
|
+
while (eqCount < len && comps1[eqCount] === comps2[eqCount]) {
|
417
|
+
++eqCount;
|
418
|
+
}
|
419
|
+
return eqCount;
|
420
|
+
};
|
421
|
+
pathsMatch = function(path1, path2) {
|
422
|
+
return numberOfMatchingSegments(path1, path2) > 0;
|
423
|
+
};
|
424
|
+
IMAGE_STYLES = [
|
425
|
+
{
|
426
|
+
selector: 'background',
|
427
|
+
styleNames: ['backgroundImage']
|
428
|
+
}, {
|
429
|
+
selector: 'border',
|
430
|
+
styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage']
|
431
|
+
}
|
432
|
+
];
|
433
|
+
__reloader.Reloader = Reloader = (function() {
|
434
|
+
function Reloader(window, console, Timer) {
|
435
|
+
this.window = window;
|
436
|
+
this.console = console;
|
437
|
+
this.Timer = Timer;
|
438
|
+
this.document = this.window.document;
|
439
|
+
this.stylesheetGracePeriod = 200;
|
440
|
+
this.importCacheWaitPeriod = 200;
|
441
|
+
this.plugins = [];
|
442
|
+
}
|
443
|
+
Reloader.prototype.addPlugin = function(plugin) {
|
444
|
+
return this.plugins.push(plugin);
|
378
445
|
};
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
if (
|
388
|
-
|
389
|
-
object: object,
|
390
|
-
score: score
|
391
|
-
};
|
446
|
+
Reloader.prototype.analyze = function(callback) {
|
447
|
+
return results;
|
448
|
+
};
|
449
|
+
Reloader.prototype.reload = function(path, options) {
|
450
|
+
var plugin, _i, _len, _ref;
|
451
|
+
_ref = this.plugins;
|
452
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
453
|
+
plugin = _ref[_i];
|
454
|
+
if (plugin.reload && plugin.reload(path, options)) {
|
455
|
+
return;
|
392
456
|
}
|
393
457
|
}
|
394
|
-
if (
|
395
|
-
|
396
|
-
|
397
|
-
return null;
|
398
|
-
}
|
399
|
-
};
|
400
|
-
numberOfMatchingSegments = function(path1, path2) {
|
401
|
-
var comps1, comps2, eqCount, len;
|
402
|
-
path1 = path1.replace(/^\/+/, '').toLowerCase();
|
403
|
-
path2 = path2.replace(/^\/+/, '').toLowerCase();
|
404
|
-
if (path1 === path2) {
|
405
|
-
return 10000;
|
406
|
-
}
|
407
|
-
comps1 = path1.split('/').reverse();
|
408
|
-
comps2 = path2.split('/').reverse();
|
409
|
-
len = Math.min(comps1.length, comps2.length);
|
410
|
-
eqCount = 0;
|
411
|
-
while (eqCount < len && comps1[eqCount] === comps2[eqCount]) {
|
412
|
-
++eqCount;
|
413
|
-
}
|
414
|
-
return eqCount;
|
415
|
-
};
|
416
|
-
pathsMatch = function(path1, path2) {
|
417
|
-
return numberOfMatchingSegments(path1, path2) > 0;
|
418
|
-
};
|
419
|
-
IMAGE_STYLES = [
|
420
|
-
{
|
421
|
-
selector: 'background',
|
422
|
-
styleNames: ['backgroundImage']
|
423
|
-
}, {
|
424
|
-
selector: 'border',
|
425
|
-
styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage']
|
426
|
-
}
|
427
|
-
];
|
428
|
-
__reloader.Reloader = Reloader = (function() {
|
429
|
-
function Reloader(window, console, Timer) {
|
430
|
-
this.window = window;
|
431
|
-
this.console = console;
|
432
|
-
this.Timer = Timer;
|
433
|
-
this.document = this.window.document;
|
434
|
-
this.stylesheetGracePeriod = 200;
|
435
|
-
this.importCacheWaitPeriod = 200;
|
436
|
-
}
|
437
|
-
Reloader.prototype.reload = function(path, options) {
|
438
|
-
if (options.liveCSS) {
|
439
|
-
if (path.match(/\.css$/i)) {
|
440
|
-
if (this.reloadStylesheet(path)) {
|
441
|
-
return;
|
442
|
-
}
|
443
|
-
}
|
444
|
-
if (path.match(/\.less$/i) && this.window.less && this.window.less.refresh) {
|
445
|
-
this.window.less.refresh(true);
|
458
|
+
if (options.liveCSS) {
|
459
|
+
if (path.match(/\.css$/i)) {
|
460
|
+
if (this.reloadStylesheet(path)) {
|
446
461
|
return;
|
447
462
|
}
|
448
463
|
}
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
464
|
+
}
|
465
|
+
if (options.liveImg) {
|
466
|
+
if (path.match(/\.(jpe?g|png|gif)$/i)) {
|
467
|
+
this.reloadImages(path);
|
468
|
+
return;
|
454
469
|
}
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
470
|
+
}
|
471
|
+
return this.reloadPage();
|
472
|
+
};
|
473
|
+
Reloader.prototype.reloadPage = function() {
|
474
|
+
return this.window.document.location.reload();
|
475
|
+
};
|
476
|
+
Reloader.prototype.reloadImages = function(path) {
|
477
|
+
var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len2, _len3, _len4, _ref, _ref2, _ref3, _ref4, _results;
|
478
|
+
expando = this.generateUniqueString();
|
479
|
+
_ref = this.document.images;
|
480
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
481
|
+
img = _ref[_i];
|
482
|
+
if (pathsMatch(path, pathFromUrl(img.src))) {
|
483
|
+
img.src = this.generateCacheBustUrl(img.src, expando);
|
484
|
+
}
|
485
|
+
}
|
486
|
+
if (this.document.querySelectorAll) {
|
487
|
+
for (_j = 0, _len2 = IMAGE_STYLES.length; _j < _len2; _j++) {
|
488
|
+
_ref2 = IMAGE_STYLES[_j], selector = _ref2.selector, styleNames = _ref2.styleNames;
|
489
|
+
_ref3 = this.document.querySelectorAll("[style*=" + selector + "]");
|
490
|
+
for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) {
|
491
|
+
img = _ref3[_k];
|
492
|
+
this.reloadStyleImages(img.style, styleNames, path, expando);
|
468
493
|
}
|
469
494
|
}
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
495
|
+
}
|
496
|
+
if (this.document.styleSheets) {
|
497
|
+
_ref4 = this.document.styleSheets;
|
498
|
+
_results = [];
|
499
|
+
for (_l = 0, _len4 = _ref4.length; _l < _len4; _l++) {
|
500
|
+
styleSheet = _ref4[_l];
|
501
|
+
_results.push(this.reloadStylesheetImages(styleSheet, path, expando));
|
502
|
+
}
|
503
|
+
return _results;
|
504
|
+
}
|
505
|
+
};
|
506
|
+
Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) {
|
507
|
+
var rule, rules, styleNames, _i, _j, _len, _len2;
|
508
|
+
try {
|
509
|
+
rules = styleSheet != null ? styleSheet.cssRules : void 0;
|
510
|
+
} catch (e) {
|
511
|
+
|
512
|
+
}
|
513
|
+
if (!rules) {
|
514
|
+
return;
|
515
|
+
}
|
516
|
+
for (_i = 0, _len = rules.length; _i < _len; _i++) {
|
517
|
+
rule = rules[_i];
|
518
|
+
switch (rule.type) {
|
519
|
+
case CSSRule.IMPORT_RULE:
|
520
|
+
this.reloadStylesheetImages(rule.styleSheet, path, expando);
|
521
|
+
break;
|
522
|
+
case CSSRule.STYLE_RULE:
|
523
|
+
for (_j = 0, _len2 = IMAGE_STYLES.length; _j < _len2; _j++) {
|
524
|
+
styleNames = IMAGE_STYLES[_j].styleNames;
|
525
|
+
this.reloadStyleImages(rule.style, styleNames, path, expando);
|
526
|
+
}
|
527
|
+
break;
|
528
|
+
case CSSRule.MEDIA_RULE:
|
529
|
+
this.reloadStylesheetImages(rule, path, expando);
|
530
|
+
}
|
531
|
+
}
|
532
|
+
};
|
533
|
+
Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) {
|
534
|
+
var newValue, styleName, value, _i, _len;
|
535
|
+
for (_i = 0, _len = styleNames.length; _i < _len; _i++) {
|
536
|
+
styleName = styleNames[_i];
|
537
|
+
value = style[styleName];
|
538
|
+
if (typeof value === 'string') {
|
539
|
+
newValue = value.replace(/\burl\s*\(([^)]*)\)/, __bind(function(match, src) {
|
540
|
+
if (pathsMatch(path, pathFromUrl(src))) {
|
541
|
+
return "url(" + (this.generateCacheBustUrl(src, expando)) + ")";
|
542
|
+
} else {
|
543
|
+
return match;
|
477
544
|
}
|
545
|
+
}, this));
|
546
|
+
if (newValue !== value) {
|
547
|
+
style[styleName] = newValue;
|
478
548
|
}
|
479
549
|
}
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
550
|
+
}
|
551
|
+
};
|
552
|
+
Reloader.prototype.reloadStylesheet = function(path) {
|
553
|
+
var imported, link, links, match, style, _i, _j, _k, _len, _len2, _len3, _ref;
|
554
|
+
links = (function() {
|
555
|
+
var _i, _len, _ref, _results;
|
556
|
+
_ref = this.document.getElementsByTagName('link');
|
557
|
+
_results = [];
|
558
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
559
|
+
link = _ref[_i];
|
560
|
+
if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) {
|
561
|
+
_results.push(link);
|
486
562
|
}
|
487
|
-
return _results;
|
488
563
|
}
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
564
|
+
return _results;
|
565
|
+
}).call(this);
|
566
|
+
imported = [];
|
567
|
+
_ref = this.document.getElementsByTagName('style');
|
568
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
569
|
+
style = _ref[_i];
|
570
|
+
if (style.sheet) {
|
571
|
+
this.collectImportedStylesheets(style, style.sheet, imported);
|
496
572
|
}
|
497
|
-
|
498
|
-
|
573
|
+
}
|
574
|
+
for (_j = 0, _len2 = links.length; _j < _len2; _j++) {
|
575
|
+
link = links[_j];
|
576
|
+
this.collectImportedStylesheets(link, link.sheet, imported);
|
577
|
+
}
|
578
|
+
this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets");
|
579
|
+
match = pickBestMatch(path, links.concat(imported), function(l) {
|
580
|
+
return pathFromUrl(l.href);
|
581
|
+
});
|
582
|
+
if (match) {
|
583
|
+
if (match.object.rule) {
|
584
|
+
this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href);
|
585
|
+
this.reattachImportedRule(match.object);
|
586
|
+
} else {
|
587
|
+
this.console.log("LiveReload is reloading stylesheet: " + match.object.href);
|
588
|
+
this.reattachStylesheetLink(match.object);
|
589
|
+
}
|
590
|
+
} else {
|
591
|
+
this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one");
|
592
|
+
for (_k = 0, _len3 = links.length; _k < _len3; _k++) {
|
593
|
+
link = links[_k];
|
594
|
+
this.reattachStylesheetLink(link);
|
499
595
|
}
|
500
|
-
|
501
|
-
|
596
|
+
}
|
597
|
+
return true;
|
598
|
+
};
|
599
|
+
Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) {
|
600
|
+
var index, rule, rules, _len;
|
601
|
+
try {
|
602
|
+
rules = styleSheet != null ? styleSheet.cssRules : void 0;
|
603
|
+
} catch (e) {
|
604
|
+
|
605
|
+
}
|
606
|
+
if (rules && rules.length) {
|
607
|
+
for (index = 0, _len = rules.length; index < _len; index++) {
|
608
|
+
rule = rules[index];
|
502
609
|
switch (rule.type) {
|
610
|
+
case CSSRule.CHARSET_RULE:
|
611
|
+
continue;
|
503
612
|
case CSSRule.IMPORT_RULE:
|
504
|
-
|
613
|
+
result.push({
|
614
|
+
link: link,
|
615
|
+
rule: rule,
|
616
|
+
index: index,
|
617
|
+
href: rule.href
|
618
|
+
});
|
619
|
+
this.collectImportedStylesheets(link, rule.styleSheet, result);
|
505
620
|
break;
|
506
|
-
|
507
|
-
for (_j = 0, _len2 = IMAGE_STYLES.length; _j < _len2; _j++) {
|
508
|
-
styleNames = IMAGE_STYLES[_j].styleNames;
|
509
|
-
this.reloadStyleImages(rule.style, styleNames, path, expando);
|
510
|
-
}
|
621
|
+
default:
|
511
622
|
break;
|
512
|
-
case CSSRule.MEDIA_RULE:
|
513
|
-
this.reloadStylesheetImages(rule, path, expando);
|
514
623
|
}
|
515
624
|
}
|
516
|
-
}
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
};
|
536
|
-
Reloader.prototype.reloadStylesheet = function(path) {
|
537
|
-
var imported, link, links, match, _i, _j, _len, _len2;
|
538
|
-
links = (function() {
|
539
|
-
var _i, _len, _ref, _results;
|
540
|
-
_ref = this.document.getElementsByTagName('link');
|
541
|
-
_results = [];
|
542
|
-
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
543
|
-
link = _ref[_i];
|
544
|
-
if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) {
|
545
|
-
_results.push(link);
|
546
|
-
}
|
547
|
-
}
|
548
|
-
return _results;
|
549
|
-
}).call(this);
|
550
|
-
imported = [];
|
551
|
-
for (_i = 0, _len = links.length; _i < _len; _i++) {
|
552
|
-
link = links[_i];
|
553
|
-
this.collectImportedStylesheets(link, link.sheet, imported);
|
554
|
-
}
|
555
|
-
this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets");
|
556
|
-
match = pickBestMatch(path, links.concat(imported), function(l) {
|
557
|
-
return pathFromUrl(l.href);
|
558
|
-
});
|
559
|
-
if (match) {
|
560
|
-
if (match.object.rule) {
|
561
|
-
this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href);
|
562
|
-
this.reattachImportedRule(match.object);
|
563
|
-
} else {
|
564
|
-
this.console.log("LiveReload is reloading stylesheet: " + match.object.href);
|
565
|
-
this.reattachStylesheetLink(match.object);
|
566
|
-
}
|
567
|
-
} else {
|
568
|
-
this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one");
|
569
|
-
for (_j = 0, _len2 = links.length; _j < _len2; _j++) {
|
570
|
-
link = links[_j];
|
571
|
-
this.reattachStylesheetLink(link);
|
572
|
-
}
|
573
|
-
}
|
574
|
-
return true;
|
575
|
-
};
|
576
|
-
Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) {
|
577
|
-
var index, rule, rules, _len;
|
578
|
-
try {
|
579
|
-
rules = styleSheet != null ? styleSheet.cssRules : void 0;
|
580
|
-
} catch (e) {
|
581
|
-
|
625
|
+
}
|
626
|
+
};
|
627
|
+
Reloader.prototype.reattachStylesheetLink = function(link) {
|
628
|
+
var clone, parent, timer;
|
629
|
+
if (link.__LiveReload_pendingRemoval) {
|
630
|
+
return;
|
631
|
+
}
|
632
|
+
link.__LiveReload_pendingRemoval = true;
|
633
|
+
clone = link.cloneNode(false);
|
634
|
+
clone.href = this.generateCacheBustUrl(link.href);
|
635
|
+
parent = link.parentNode;
|
636
|
+
if (parent.lastChild === link) {
|
637
|
+
parent.appendChild(clone);
|
638
|
+
} else {
|
639
|
+
parent.insertBefore(clone, link.nextSibling);
|
640
|
+
}
|
641
|
+
timer = new this.Timer(function() {
|
642
|
+
if (link.parentNode) {
|
643
|
+
return link.parentNode.removeChild(link);
|
582
644
|
}
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
645
|
+
});
|
646
|
+
return timer.start(this.stylesheetGracePeriod);
|
647
|
+
};
|
648
|
+
Reloader.prototype.reattachImportedRule = function(_arg) {
|
649
|
+
var href, index, link, media, newRule, parent, rule, tempLink;
|
650
|
+
rule = _arg.rule, index = _arg.index, link = _arg.link;
|
651
|
+
parent = rule.parentStyleSheet;
|
652
|
+
href = this.generateCacheBustUrl(rule.href);
|
653
|
+
media = rule.media.length ? [].join.call(rule.media, ', ') : '';
|
654
|
+
newRule = "@import url(\"" + href + "\") " + media + ";";
|
655
|
+
rule.__LiveReload_newHref = href;
|
656
|
+
tempLink = this.document.createElement("link");
|
657
|
+
tempLink.rel = 'stylesheet';
|
658
|
+
tempLink.href = href;
|
659
|
+
tempLink.__LiveReload_pendingRemoval = true;
|
660
|
+
if (link.parentNode) {
|
661
|
+
link.parentNode.insertBefore(tempLink, link);
|
662
|
+
}
|
663
|
+
return this.Timer.start(this.importCacheWaitPeriod, __bind(function() {
|
664
|
+
if (tempLink.parentNode) {
|
665
|
+
tempLink.parentNode.removeChild(tempLink);
|
602
666
|
}
|
603
|
-
|
604
|
-
Reloader.prototype.reattachStylesheetLink = function(link) {
|
605
|
-
var clone, parent, timer;
|
606
|
-
if (link.__LiveReload_pendingRemoval) {
|
667
|
+
if (rule.__LiveReload_newHref !== href) {
|
607
668
|
return;
|
608
669
|
}
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
parent = link.parentNode;
|
613
|
-
if (parent.lastChild === link) {
|
614
|
-
parent.appendChild(clone);
|
615
|
-
} else {
|
616
|
-
parent.insertBefore(clone, link.nextSibling);
|
617
|
-
}
|
618
|
-
timer = new this.Timer(function() {
|
619
|
-
if (link.parentNode) {
|
620
|
-
return link.parentNode.removeChild(link);
|
621
|
-
}
|
622
|
-
});
|
623
|
-
return timer.start(this.stylesheetGracePeriod);
|
624
|
-
};
|
625
|
-
Reloader.prototype.reattachImportedRule = function(_arg) {
|
626
|
-
var href, index, link, media, newRule, parent, rule, tempLink;
|
627
|
-
rule = _arg.rule, index = _arg.index, link = _arg.link;
|
628
|
-
parent = rule.parentStyleSheet;
|
629
|
-
href = this.generateCacheBustUrl(rule.href);
|
630
|
-
media = rule.media.length ? [].join.call(rule.media, ', ') : '';
|
631
|
-
newRule = "@import url(\"" + href + "\") " + media + ";";
|
670
|
+
parent.insertRule(newRule, index);
|
671
|
+
parent.deleteRule(index + 1);
|
672
|
+
rule = parent.cssRules[index];
|
632
673
|
rule.__LiveReload_newHref = href;
|
633
|
-
tempLink = this.document.createElement("link");
|
634
|
-
tempLink.rel = 'stylesheet';
|
635
|
-
tempLink.href = href;
|
636
|
-
tempLink.__LiveReload_pendingRemoval = true;
|
637
|
-
if (link.parentNode) {
|
638
|
-
link.parentNode.insertBefore(tempLink, link);
|
639
|
-
}
|
640
674
|
return this.Timer.start(this.importCacheWaitPeriod, __bind(function() {
|
641
|
-
if (tempLink.parentNode) {
|
642
|
-
tempLink.parentNode.removeChild(tempLink);
|
643
|
-
}
|
644
675
|
if (rule.__LiveReload_newHref !== href) {
|
645
676
|
return;
|
646
677
|
}
|
647
678
|
parent.insertRule(newRule, index);
|
648
|
-
parent.deleteRule(index + 1);
|
649
|
-
rule = parent.cssRules[index];
|
650
|
-
rule.__LiveReload_newHref = href;
|
651
|
-
return this.Timer.start(this.importCacheWaitPeriod, __bind(function() {
|
652
|
-
if (rule.__LiveReload_newHref !== href) {
|
653
|
-
return;
|
654
|
-
}
|
655
|
-
parent.insertRule(newRule, index);
|
656
|
-
return parent.deleteRule(index + 1);
|
657
|
-
}, this));
|
679
|
+
return parent.deleteRule(index + 1);
|
658
680
|
}, this));
|
659
|
-
};
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
681
|
+
}, this));
|
682
|
+
};
|
683
|
+
Reloader.prototype.generateUniqueString = function() {
|
684
|
+
return 'livereload=' + Date.now();
|
685
|
+
};
|
686
|
+
Reloader.prototype.generateCacheBustUrl = function(url, expando) {
|
687
|
+
var hash, oldParams, params, _ref;
|
688
|
+
if (expando == null) {
|
689
|
+
expando = this.generateUniqueString();
|
690
|
+
}
|
691
|
+
_ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params;
|
692
|
+
params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) {
|
693
|
+
return "" + sep + expando;
|
694
|
+
});
|
695
|
+
if (params === oldParams) {
|
696
|
+
if (oldParams.length === 0) {
|
697
|
+
params = "?" + expando;
|
698
|
+
} else {
|
699
|
+
params = "" + oldParams + "&" + expando;
|
667
700
|
}
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
701
|
+
}
|
702
|
+
return url + params + hash;
|
703
|
+
};
|
704
|
+
return Reloader;
|
705
|
+
})();
|
706
|
+
|
707
|
+
// livereload
|
708
|
+
var Connector, LiveReload, Options, Reloader, Timer;
|
709
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
710
|
+
Connector = __connector.Connector;
|
711
|
+
Timer = __timer.Timer;
|
712
|
+
Options = __options.Options;
|
713
|
+
Reloader = __reloader.Reloader;
|
714
|
+
__livereload.LiveReload = LiveReload = (function() {
|
715
|
+
function LiveReload(window) {
|
716
|
+
this.window = window;
|
717
|
+
this.listeners = {};
|
718
|
+
this.plugins = [];
|
719
|
+
this.pluginIdentifiers = {};
|
720
|
+
this.console = this.window.console && this.window.console.log && this.window.console.error ? this.window.console : {
|
721
|
+
log: function() {},
|
722
|
+
error: function() {}
|
723
|
+
};
|
724
|
+
if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) {
|
725
|
+
console.error("LiveReload disabled because the browser does not seem to support web sockets");
|
726
|
+
return;
|
727
|
+
}
|
728
|
+
if (!(this.options = Options.extract(this.window.document))) {
|
729
|
+
console.error("LiveReload disabled because it could not find its own <SCRIPT> tag");
|
730
|
+
return;
|
731
|
+
}
|
732
|
+
this.reloader = new Reloader(this.window, this.console, Timer);
|
733
|
+
this.connector = new Connector(this.options, this.WebSocket, Timer, {
|
734
|
+
connecting: __bind(function() {}, this),
|
735
|
+
socketConnected: __bind(function() {}, this),
|
736
|
+
connected: __bind(function(protocol) {
|
737
|
+
var _base;
|
738
|
+
if (typeof (_base = this.listeners).connect === "function") {
|
739
|
+
_base.connect();
|
740
|
+
}
|
741
|
+
this.log("LiveReload is connected to " + this.options.host + ":" + this.options.port + " (protocol v" + protocol + ").");
|
742
|
+
return this.analyze();
|
743
|
+
}, this),
|
744
|
+
error: __bind(function(e) {
|
745
|
+
if (e instanceof ProtocolError) {
|
746
|
+
return console.log("" + e.message + ".");
|
675
747
|
} else {
|
676
|
-
|
748
|
+
return console.log("LiveReload internal error: " + e.message);
|
677
749
|
}
|
678
|
-
}
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
}
|
750
|
+
}, this),
|
751
|
+
disconnected: __bind(function(reason, nextDelay) {
|
752
|
+
var _base;
|
753
|
+
if (typeof (_base = this.listeners).disconnect === "function") {
|
754
|
+
_base.disconnect();
|
755
|
+
}
|
756
|
+
switch (reason) {
|
757
|
+
case 'cannot-connect':
|
758
|
+
return this.log("LiveReload cannot connect to " + this.options.host + ":" + this.options.port + ", will retry in " + nextDelay + " sec.");
|
759
|
+
case 'broken':
|
760
|
+
return this.log("LiveReload disconnected from " + this.options.host + ":" + this.options.port + ", reconnecting in " + nextDelay + " sec.");
|
761
|
+
case 'handshake-timeout':
|
762
|
+
return this.log("LiveReload cannot connect to " + this.options.host + ":" + this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec.");
|
763
|
+
case 'handshake-failed':
|
764
|
+
return this.log("LiveReload cannot connect to " + this.options.host + ":" + this.options.port + " (handshake failed), will retry in " + nextDelay + " sec.");
|
765
|
+
case 'manual':
|
766
|
+
break;
|
767
|
+
case 'error':
|
768
|
+
break;
|
769
|
+
default:
|
770
|
+
return this.log("LiveReload disconnected from " + this.options.host + ":" + this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec.");
|
771
|
+
}
|
772
|
+
}, this),
|
773
|
+
message: __bind(function(message) {
|
774
|
+
switch (message.command) {
|
775
|
+
case 'reload':
|
776
|
+
return this.performReload(message);
|
777
|
+
case 'alert':
|
778
|
+
return this.performAlert(message);
|
779
|
+
}
|
780
|
+
}, this)
|
781
|
+
});
|
782
|
+
}
|
783
|
+
LiveReload.prototype.on = function(eventName, handler) {
|
784
|
+
return this.listeners[eventName] = handler;
|
785
|
+
};
|
786
|
+
LiveReload.prototype.log = function(message) {
|
787
|
+
return this.console.log("" + message);
|
788
|
+
};
|
789
|
+
LiveReload.prototype.performReload = function(message) {
|
790
|
+
var _ref, _ref2;
|
791
|
+
this.log("LiveReload received reload request for " + message.path + ".");
|
792
|
+
return this.reloader.reload(message.path, {
|
793
|
+
liveCSS: (_ref = message.liveCSS) != null ? _ref : true,
|
794
|
+
liveImg: (_ref2 = message.liveImg) != null ? _ref2 : true,
|
795
|
+
originalPath: message.originalPath || ''
|
796
|
+
});
|
797
|
+
};
|
798
|
+
LiveReload.prototype.performAlert = function(message) {
|
799
|
+
return alert(message.message);
|
800
|
+
};
|
801
|
+
LiveReload.prototype.shutDown = function() {
|
802
|
+
var _base;
|
803
|
+
this.connector.disconnect();
|
804
|
+
this.log("LiveReload disconnected.");
|
805
|
+
return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0;
|
806
|
+
};
|
807
|
+
LiveReload.prototype.hasPlugin = function(identifier) {
|
808
|
+
return !!this.pluginIdentifiers[identifier];
|
809
|
+
};
|
810
|
+
LiveReload.prototype.addPlugin = function(pluginClass) {
|
811
|
+
var plugin;
|
812
|
+
if (this.hasPlugin(pluginClass.identifier)) {
|
813
|
+
return;
|
814
|
+
}
|
815
|
+
this.pluginIdentifiers[pluginClass.identifier] = true;
|
816
|
+
plugin = new pluginClass(this.window, {
|
817
|
+
_livereload: this,
|
818
|
+
_reloader: this.reloader,
|
819
|
+
_connector: this.connector,
|
820
|
+
console: this.console,
|
821
|
+
Timer: Timer,
|
822
|
+
generateCacheBustUrl: __bind(function(url) {
|
823
|
+
return this.reloader.generateCacheBustUrl(url);
|
824
|
+
}, this)
|
825
|
+
});
|
826
|
+
this.plugins.push(plugin);
|
827
|
+
this.reloader.addPlugin(plugin);
|
828
|
+
};
|
829
|
+
LiveReload.prototype.analyze = function() {
|
830
|
+
var plugin, pluginData, pluginsData, _i, _len, _ref;
|
831
|
+
if (!(this.connector.protocol >= 7)) {
|
832
|
+
return;
|
833
|
+
}
|
834
|
+
pluginsData = {};
|
835
|
+
_ref = this.plugins;
|
836
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
837
|
+
plugin = _ref[_i];
|
838
|
+
pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {};
|
839
|
+
pluginData.version = plugin.constructor.version;
|
840
|
+
}
|
841
|
+
this.connector.sendCommand({
|
842
|
+
command: 'info',
|
843
|
+
plugins: pluginsData,
|
844
|
+
url: this.window.location.href
|
845
|
+
});
|
846
|
+
};
|
847
|
+
return LiveReload;
|
848
|
+
})();
|
684
849
|
|
685
|
-
//
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) {
|
702
|
-
console.error("LiveReload disabled because the browser does not seem to support web sockets");
|
703
|
-
return;
|
850
|
+
// less
|
851
|
+
var LessPlugin;
|
852
|
+
__less = LessPlugin = (function() {
|
853
|
+
LessPlugin.identifier = 'less';
|
854
|
+
LessPlugin.version = '1.0';
|
855
|
+
function LessPlugin(window, host) {
|
856
|
+
this.window = window;
|
857
|
+
this.host = host;
|
858
|
+
}
|
859
|
+
LessPlugin.prototype.reload = function(path, options) {
|
860
|
+
if (this.window.less && this.window.less.refresh) {
|
861
|
+
if (path.match(/\.less$/i)) {
|
862
|
+
return this.reloadLess(path);
|
863
|
+
}
|
864
|
+
if (options.originalPath.match(/\.less$/i)) {
|
865
|
+
return this.reloadLess(options.originalPath);
|
704
866
|
}
|
705
|
-
|
706
|
-
|
707
|
-
|
867
|
+
}
|
868
|
+
return false;
|
869
|
+
};
|
870
|
+
LessPlugin.prototype.reloadLess = function(path) {
|
871
|
+
var link, links, _i, _len;
|
872
|
+
links = (function() {
|
873
|
+
var _i, _len, _ref, _results;
|
874
|
+
_ref = document.getElementsByTagName('link');
|
875
|
+
_results = [];
|
876
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
877
|
+
link = _ref[_i];
|
878
|
+
if (link.href && link.rel === 'stylesheet/less' || (link.rel.match(/stylesheet/) && link.type.match(/^text\/(x-)?less$/))) {
|
879
|
+
_results.push(link);
|
880
|
+
}
|
708
881
|
}
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
connected: __bind(function(protocol) {
|
714
|
-
var _base;
|
715
|
-
if (typeof (_base = this.listeners).connect === "function") {
|
716
|
-
_base.connect();
|
717
|
-
}
|
718
|
-
return this.log("LiveReload is connected to " + this.options.host + ":" + this.options.port + " (protocol v" + protocol + ").");
|
719
|
-
}, this),
|
720
|
-
error: __bind(function(e) {
|
721
|
-
if (e instanceof ProtocolError) {
|
722
|
-
return console.log("" + e.message + ".");
|
723
|
-
} else {
|
724
|
-
return console.log("LiveReload internal error: " + e.message);
|
725
|
-
}
|
726
|
-
}, this),
|
727
|
-
disconnected: __bind(function(reason, nextDelay) {
|
728
|
-
var _base;
|
729
|
-
if (typeof (_base = this.listeners).disconnect === "function") {
|
730
|
-
_base.disconnect();
|
731
|
-
}
|
732
|
-
switch (reason) {
|
733
|
-
case 'cannot-connect':
|
734
|
-
return this.log("LiveReload cannot connect to " + this.options.host + ":" + this.options.port + ", will retry in " + nextDelay + " sec.");
|
735
|
-
case 'broken':
|
736
|
-
return this.log("LiveReload disconnected from " + this.options.host + ":" + this.options.port + ", reconnecting in " + nextDelay + " sec.");
|
737
|
-
case 'handshake-timeout':
|
738
|
-
return this.log("LiveReload cannot connect to " + this.options.host + ":" + this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec.");
|
739
|
-
case 'handshake-failed':
|
740
|
-
return this.log("LiveReload cannot connect to " + this.options.host + ":" + this.options.port + " (handshake failed), will retry in " + nextDelay + " sec.");
|
741
|
-
case 'manual':
|
742
|
-
break;
|
743
|
-
case 'error':
|
744
|
-
break;
|
745
|
-
default:
|
746
|
-
return this.log("LiveReload disconnected from " + this.options.host + ":" + this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec.");
|
747
|
-
}
|
748
|
-
}, this),
|
749
|
-
message: __bind(function(message) {
|
750
|
-
switch (message.command) {
|
751
|
-
case 'reload':
|
752
|
-
return this.performReload(message);
|
753
|
-
case 'alert':
|
754
|
-
return this.performAlert(message);
|
755
|
-
}
|
756
|
-
}, this)
|
757
|
-
});
|
882
|
+
return _results;
|
883
|
+
})();
|
884
|
+
if (links.length === 0) {
|
885
|
+
return false;
|
758
886
|
}
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
liveImg: (_ref2 = message.liveImg) != null ? _ref2 : true
|
771
|
-
});
|
772
|
-
};
|
773
|
-
LiveReload.prototype.performAlert = function(message) {
|
774
|
-
return alert(message.message);
|
775
|
-
};
|
776
|
-
LiveReload.prototype.shutDown = function() {
|
777
|
-
var _base;
|
778
|
-
this.connector.disconnect();
|
779
|
-
this.log("LiveReload disconnected.");
|
780
|
-
return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0;
|
887
|
+
for (_i = 0, _len = links.length; _i < _len; _i++) {
|
888
|
+
link = links[_i];
|
889
|
+
link.href = this.host.generateCacheBustUrl(link.href);
|
890
|
+
}
|
891
|
+
this.host.console.log("LiveReload is asking LESS to recompile all stylesheets");
|
892
|
+
this.window.less.refresh(true);
|
893
|
+
return true;
|
894
|
+
};
|
895
|
+
LessPlugin.prototype.analyze = function() {
|
896
|
+
return {
|
897
|
+
disable: !!(this.window.less && this.window.less.refresh)
|
781
898
|
};
|
782
|
-
|
783
|
-
|
784
|
-
})
|
899
|
+
};
|
900
|
+
return LessPlugin;
|
901
|
+
})();
|
785
902
|
|
786
903
|
// startup
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
904
|
+
var CustomEvents, LiveReload, k, v;
|
905
|
+
CustomEvents = __customevents;
|
906
|
+
LiveReload = window.LiveReload = new (__livereload.LiveReload)(window);
|
907
|
+
for (k in window) {
|
908
|
+
v = window[k];
|
909
|
+
if (k.match(/^LiveReloadPlugin/)) {
|
910
|
+
LiveReload.addPlugin(v);
|
911
|
+
}
|
912
|
+
}
|
913
|
+
LiveReload.addPlugin(__less);
|
914
|
+
LiveReload.on('shutdown', function() {
|
915
|
+
return delete window.LiveReload;
|
916
|
+
});
|
917
|
+
LiveReload.on('connect', function() {
|
918
|
+
return CustomEvents.fire(document, 'LiveReloadConnect');
|
919
|
+
});
|
920
|
+
LiveReload.on('disconnect', function() {
|
921
|
+
return CustomEvents.fire(document, 'LiveReloadDisconnect');
|
922
|
+
});
|
923
|
+
CustomEvents.bind(document, 'LiveReloadShutDown', function() {
|
924
|
+
return LiveReload.shutDown();
|
925
|
+
});
|
804
926
|
})();
|