hyla 1.0

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.
Files changed (72) hide show
  1. data/.rakeTasks +7 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +7 -0
  4. data/Gemfile.lock +49 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.adoc +136 -0
  7. data/Rakefile +61 -0
  8. data/archive/GruntFile.js +72 -0
  9. data/archive/watch_files.rb +70 -0
  10. data/bin/hyla +155 -0
  11. data/data/generated/A_Introduction_module/1_Chapter.adoc +42 -0
  12. data/data/generated/A_Introduction_module/2_Chapter.adoc +31 -0
  13. data/data/generated/A_Introduction_module/3_Chapter.adoc +23 -0
  14. data/data/generated/A_Introduction_module/A_Introduction_module_AllSlides.index +9 -0
  15. data/data/generated/B_Instruction_module/1_Chapter.adoc +27 -0
  16. data/data/generated/B_Instruction_module/B_Instruction_module_AllSlides.index +7 -0
  17. data/data/generated/C_Installation_module/1_Chapter.adoc +14 -0
  18. data/data/generated/C_Installation_module/2_Chapter.adoc +17 -0
  19. data/data/generated/C_Installation_module/C_Installation_module_AllSlides.index +8 -0
  20. data/data/generated/camel_AllSlides.index +9 -0
  21. data/data/js/livereload.js +1055 -0
  22. data/data/mime.types +85 -0
  23. data/data/toc.adoc +63 -0
  24. data/hyla.gemspec +37 -0
  25. data/hyla_frog.jpg +0 -0
  26. data/lib/hyla.rb +47 -0
  27. data/lib/hyla/command.rb +21 -0
  28. data/lib/hyla/commands/build.rb +40 -0
  29. data/lib/hyla/commands/create.rb +25 -0
  30. data/lib/hyla/commands/generate.rb +264 -0
  31. data/lib/hyla/commands/new.rb +82 -0
  32. data/lib/hyla/commands/publish.rb +8 -0
  33. data/lib/hyla/commands/reload.rb +109 -0
  34. data/lib/hyla/commands/serve.rb +59 -0
  35. data/lib/hyla/commands/watch.rb +172 -0
  36. data/lib/hyla/configuration.rb +47 -0
  37. data/lib/hyla/logger.rb +89 -0
  38. data/lib/hyla/project.rb +5 -0
  39. data/lib/hyla/training.rb +25 -0
  40. data/lib/hyla/websocket.rb +53 -0
  41. data/lib/templates/sample/asciidoc_article.adoc +64 -0
  42. data/lib/templates/sample/asciidoc_audio.adoc +4 -0
  43. data/lib/templates/sample/asciidoc_source_highlight.adoc +37 -0
  44. data/lib/templates/sample/asciidoc_video.adoc +4 -0
  45. data/lib/templates/sample/audio/ocean_waves.mp3 +0 -0
  46. data/lib/templates/sample/image/hyla_arborea.jpg +0 -0
  47. data/lib/templates/sample/slideshow_deckjs.adoc +186 -0
  48. data/lib/templates/sample/video/small.ogv +0 -0
  49. data/lib/templates/training-exercises/Gemfile +4 -0
  50. data/lib/templates/training-exercises/README.md +1 -0
  51. data/lib/templates/training-exercises/modules/introduction/docs/audio/ocean_waves.mp3 +0 -0
  52. data/lib/templates/training-exercises/modules/introduction/docs/video/small.ogv +0 -0
  53. data/lib/templates/training-exercises/modules/introduction/pom.xml +114 -0
  54. data/lib/templates/training-exercises/modules/introduction/src/main/java/HelloWorld.java +16 -0
  55. data/lib/templates/training-exercises/modules/introduction/src/test/java/HelloWorldTest.java +29 -0
  56. data/lib/templates/training-exercises/modules/pom.xml +61 -0
  57. data/lib/templates/training-exercises/modules/src/main/assembly/code.xml +31 -0
  58. data/lib/templates/training-exercises/modules/src/main/assembly/content.xml +16 -0
  59. data/lib/templates/training-exercises/pom.xml +157 -0
  60. data/lib/templates/training/GemFile +4 -0
  61. data/lib/templates/training/development/article.adoc +64 -0
  62. data/lib/templates/training/development/audio/ocean_waves.mp3 +0 -0
  63. data/lib/templates/training/development/image/hyla_frog.jpg +0 -0
  64. data/lib/templates/training/development/video/small.ogv +0 -0
  65. data/lib/templates/training/introduction/article.adoc +64 -0
  66. data/lib/templates/training/introduction/audio/ocean_waves.mp3 +0 -0
  67. data/lib/templates/training/introduction/image/hyla_frog.jpg +0 -0
  68. data/lib/templates/training/introduction/video/small.ogv +0 -0
  69. data/lib/templates/training/readme.adoc +1 -0
  70. data/scenario.adoc +59 -0
  71. data/test/my_test.rb +23 -0
  72. metadata +265 -0
data/bin/hyla ADDED
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ STDOUT.sync = true
4
+
5
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
6
+
7
+ if RUBY_VERSION < '1.9'
8
+ require 'rubygems'
9
+ end
10
+
11
+ require 'commander/import'
12
+ require 'hyla'
13
+ require 'hyla/project'
14
+
15
+ program :version, Hyla::VERSION
16
+ program :description, Hyla::DESCRIPTION
17
+
18
+ # global_option '-s', '--source [DIR]', 'Source directory (defaults to ./)'
19
+ # global_option '-d', '--destination [DIR]', 'Destination directory (defaults to .)'
20
+
21
+ default_command :default
22
+
23
+ def add_build_options(c)
24
+ c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
25
+ c.option '-V', '--verbose', 'Print verbose output.'
26
+ end
27
+
28
+ def add_common_options(c)
29
+ c.option '-s', '--source [DIR]', 'Source directory (defaults to ./)'
30
+ c.option '-d', '--destination [DIR]', 'Destination directory (defaults to ./generated_content)'
31
+ end
32
+
33
+ #
34
+ # Creates a new Hyla project using a template or blank to the PATH specified
35
+ #
36
+ command :new do |c|
37
+ c.syntax = 'hyla new PATH'
38
+ c.description = 'Creates a new Hyla project using a template or blank to the PATH specified'
39
+ c.option '--f','--force', 'Force creation even if PATH already exists'
40
+ c.option '--b','--blank', 'Creates project but with empty files'
41
+ c.option '--t','--template_type TEMPLATE_TYPE', String, 'Template Type to be used (documentation, training, training-exercises, blog, web, ...)'
42
+
43
+ c.action do |args, options|
44
+ Hyla::Commands::New.process(args, options.__hash__)
45
+ end
46
+ end
47
+
48
+ #
49
+ # Creates a new file from an artefact within an existing project
50
+ #
51
+ command :create do |c|
52
+ c.syntax = 'hyla create ARTEFACT TYPE'
53
+ c.description = 'Creates a new file from asciidoc artefacts for an existing project'
54
+ c.option '--a', '--artefact_type [ARTEFACT_TYPE]', String, 'Artefact Type : article, audio, video, blog entry ...'
55
+ c.option '--d', '--destination [DIR]', String, 'Destination directory'
56
+ c.option '--t', '--type [TYPE]', String, 'Type : asciidoc, slideshow'
57
+
58
+ c.action do |args, options|
59
+ Hyla::Commands::Create.process(args, options.__hash__)
60
+ end
61
+ end
62
+
63
+ #
64
+ # Generate from asciidoc files content according to rendering/transformation requested
65
+ #
66
+ command :generate do |c|
67
+ c.syntax = 'hyla generate [OPTIONS]'
68
+ c.description = 'Generate content from asciidoc files (Table Of Content, modules, ...) to HTML, Slideshow'
69
+ c.option '--s', '--source [DIR]', String, 'Directory to be watched'
70
+ c.option '--d', '--destination [DIR]', String, 'Destination directory'
71
+ c.option '--p', '--project_name [PROJECT_NAME]', String, 'Project Name'
72
+ c.option '--r', '--rendering [RENDERING]', String, 'Code of the rendering : toc2html, adoc2html'
73
+ c.option '--t', '--toc [PATH]', String, 'File Path of the asciidoc file containing the Table of Content'
74
+
75
+ c.action do |args, options|
76
+
77
+ Hyla::Commands::Generate.process(args, options.__hash__)
78
+ end
79
+ end
80
+
81
+ # Watch
82
+ command :watch do |c|
83
+ c.syntax = 'hyla watch [options]'
84
+ c.description = 'Watch directories for any change, add or file deleted and render document (HTML5)'
85
+ c.option '--d', '--destination DIR', String, 'Output directory where content must be generated'
86
+ c.option '--s', '--source DIR', String, 'Directory to be watched'
87
+ add_common_options(c)
88
+
89
+ c.action do |args, options|
90
+
91
+ options.default :serving => true
92
+
93
+ # TODO Find if it is possible to watch files, generate HTML content - asciidoctor, expose content using HTTPServe and expose WebSocket - LiveReload
94
+ # as they are started in 2 different threads, this is not possible with existing code
95
+ # Hyla::Commands::Serve.process(args,options.__hash__)
96
+ Hyla::Commands::Watch.process(args, options.__hash__)
97
+ end
98
+ end
99
+
100
+
101
+ # Serve your content locally
102
+ command :serve do |c|
103
+ c.syntax = 'hyla serve [options]'
104
+ c.description = 'Serve your content locally'
105
+ c.option '--out_dir DIR', String, 'Output directory where content must be generated'
106
+ c.option '-B', '--detach', 'Run the server in the background (detach)'
107
+ c.option '-P', '--port [PORT]', 'Port to listen on'
108
+ c.option '-H', '--host [HOST]', 'Host to bind to'
109
+ c.option '-b', '--baseurl [URL]', 'Base URL'
110
+ add_common_options(c)
111
+
112
+ c.action do |args, options|
113
+ options.default :serving => true
114
+ Hyla::Commands::Serve.process(args, options.__hash__)
115
+ end
116
+ end
117
+ alias_command :server, :serve
118
+
119
+
120
+ # NOT YET AVAILABLE
121
+
122
+ =begin
123
+ # TODO NOT FINALISED
124
+ # Reload
125
+ command :reload do |c|
126
+ c.syntax = 'hyla reload [options]'
127
+ c.description = 'Reload HTML files generated within the browser - Livereload using WebSocket Server'
128
+
129
+ c.action do |args, options|
130
+ Hyla::Commands::Reload.process(options.__hash__)
131
+ end
132
+ end
133
+
134
+ # Command generating output format from asciidoc files
135
+ command :build do |c|
136
+ c.syntax = 'hyla build [options]'
137
+ c.description = 'Generating output content (HTML, PDF, ManPages, ...) from asciidoc(tor) files'
138
+ c.option '--some-switch', 'Some switch that does something'
139
+
140
+ c.action do |args, options|
141
+ Hyla::Commands::Build.process(args, options.__hash__)
142
+ end
143
+ end
144
+
145
+ command :publish do |c|
146
+ c.syntax = 'hyla publish [options]'
147
+ c.description = ''
148
+ c.example 'description', 'command example'
149
+ c.option '--some-switch', 'Some switch that does something'
150
+ c.action do |args, options|
151
+ Hyla::Commands::Publish.process(args, options.__hash__)
152
+ end
153
+ end
154
+
155
+ =end
@@ -0,0 +1,42 @@
1
+ :data-uri:
2
+ :icons: font
3
+ :last-update-label!:
4
+ :source-highlighter: coderay
5
+ :toc: left
6
+
7
+ == 1. Chapter
8
+
9
+ This is a chapter about ... test
10
+
11
+ This is a chapter about ... test
12
+
13
+ This is a chapter about ... test
14
+
15
+ == 2. Chapter
16
+
17
+ This is a chapter about ... test
18
+
19
+ This is a chapter about ... test
20
+
21
+ This is a chapter about ... test
22
+
23
+ == 111. Chapter
24
+
25
+ This is a chapter about ... test
26
+
27
+ This is a chapter about ... test
28
+
29
+ This is a chapter about ... test
30
+
31
+ == 222. Chapter
32
+
33
+ This is a chapter about ... test
34
+
35
+ This is a chapter about ... test
36
+
37
+ This is a chapter about ... test
38
+
39
+
40
+
41
+
42
+
@@ -0,0 +1,31 @@
1
+ :data-uri:
2
+ :icons: font
3
+ :last-update-label!:
4
+ :source-highlighter: coderay
5
+ :toc: left
6
+
7
+ == 2. Chapter
8
+
9
+ This is a Chapter about ...
10
+
11
+ === 2.1. Section
12
+
13
+ This is a Section about ...
14
+
15
+ === 2.2. Section
16
+
17
+ This is a Section about ...
18
+ This is a Section about .....
19
+
20
+ === 2.3. Section
21
+
22
+ This is a Section about ...
23
+ This is a Section about .....
24
+
25
+ === 2.4. Section
26
+
27
+ This is a Section about ...
28
+ This is a Section about ....
29
+
30
+
31
+
@@ -0,0 +1,23 @@
1
+ :data-uri:
2
+ :icons: font
3
+ :last-update-label!:
4
+ :source-highlighter: coderay
5
+ :toc: left
6
+
7
+ == 3. Chapter
8
+
9
+ This is a Chapter about ...
10
+
11
+ === 3.1. Section
12
+
13
+ This is a Section about ...
14
+
15
+ === 3.2. Section
16
+
17
+ This is a Section about ...
18
+
19
+
20
+
21
+
22
+
23
+
@@ -0,0 +1,9 @@
1
+ == A_Introduction_module
2
+ :data-uri:
3
+ :navigation:
4
+ :menu:
5
+ :status:
6
+
7
+ include::1_Chapter.adoc[]
8
+ include::2_Chapter.adoc[]
9
+ include::3_Chapter.adoc[]
@@ -0,0 +1,27 @@
1
+ :data-uri:
2
+ :icons: font
3
+ :last-update-label!:
4
+ :source-highlighter: coderay
5
+ :toc: left
6
+
7
+ == 1. Chapter
8
+
9
+ This is a Chapter about ...
10
+
11
+ === 1.1. Section
12
+
13
+ This is a Section about ...
14
+
15
+ === 1.2. Section
16
+
17
+ This is a Section about ...
18
+
19
+ === 1.3. Section
20
+
21
+ This is a Section about ...
22
+
23
+ === 1.4. Section
24
+
25
+ This is a Section about ...
26
+
27
+
@@ -0,0 +1,7 @@
1
+ == B_Instruction_module
2
+ :data-uri:
3
+ :navigation:
4
+ :menu:
5
+ :status:
6
+
7
+ include::1_Chapter.adoc[]
@@ -0,0 +1,14 @@
1
+ :data-uri:
2
+ :icons: font
3
+ :last-update-label!:
4
+ :source-highlighter: coderay
5
+ :toc: left
6
+
7
+ == 1. Chapter
8
+
9
+ This is a Chapter about ...
10
+
11
+ === 1.1. Section
12
+
13
+ This is a Section about ...
14
+
@@ -0,0 +1,17 @@
1
+ :data-uri:
2
+ :icons: font
3
+ :last-update-label!:
4
+ :source-highlighter: coderay
5
+ :toc: left
6
+
7
+ == 2. Chapter
8
+
9
+ This is a Chapter about ...
10
+
11
+ === 2.1. Section
12
+
13
+ This is a Section about ...
14
+
15
+ === 2.2. Section
16
+
17
+ This is a Section about ...
@@ -0,0 +1,8 @@
1
+ == C_Installation_module
2
+ :data-uri:
3
+ :navigation:
4
+ :menu:
5
+ :status:
6
+
7
+ include::1_Chapter.adoc[]
8
+ include::2_Chapter.adoc[]
@@ -0,0 +1,9 @@
1
+ = camel
2
+ :data-uri:
3
+ :navigation:
4
+ :menu:
5
+ :status:
6
+
7
+ include::A_Introduction_module/A_Introduction_module_AllSlides.index[]
8
+ include::B_Instruction_module/B_Instruction_module_AllSlides.index[]
9
+ include::C_Installation_module/C_Installation_module_AllSlides.index[]
@@ -0,0 +1,1055 @@
1
+ (function() {
2
+ var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __less = {}, __startup = {};
3
+
4
+ // customevents
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();
15
+ }
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]++;
30
+ }
31
+ } else {
32
+ throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement");
33
+ }
34
+ }
35
+ };
36
+ __customevents.bind = CustomEvents.bind;
37
+ __customevents.fire = CustomEvents.fire;
38
+
39
+ // protocol
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) {
75
+ this.protocol = 6;
76
+ } else {
77
+ throw new ProtocolError("no supported protocols found");
78
+ }
79
+ }
80
+ return this.handlers.connected(this.protocol);
81
+ } else if (this.protocol === 6) {
82
+ message = JSON.parse(data);
83
+ if (!message.length) {
84
+ throw new ProtocolError("protocol 6 messages must be arrays");
85
+ }
86
+ command = message[0], options = message[1];
87
+ if (command !== 'refresh') {
88
+ throw new ProtocolError("unknown protocol 6 command");
89
+ }
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);
98
+ }
99
+ } catch (e) {
100
+ if (e instanceof ProtocolError) {
101
+ return this.handlers.error(e);
102
+ } else {
103
+ throw e;
104
+ }
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
+ // Generated by CoffeeScript 1.3.3
127
+ var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref;
128
+
129
+ _ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7;
130
+
131
+ Version = '2.0.8';
132
+
133
+ __connector.Connector = Connector = (function() {
134
+
135
+ function Connector(options, WebSocket, Timer, handlers) {
136
+ var _this = this;
137
+ this.options = options;
138
+ this.WebSocket = WebSocket;
139
+ this.Timer = Timer;
140
+ this.handlers = handlers;
141
+ this._uri = "ws://" + this.options.host + ":" + this.options.port + "/livereload";
142
+ this._nextDelay = this.options.mindelay;
143
+ this._connectionDesired = false;
144
+ this.protocol = 0;
145
+ this.protocolParser = new Parser({
146
+ connected: function(protocol) {
147
+ _this.protocol = protocol;
148
+ _this._handshakeTimeout.stop();
149
+ _this._nextDelay = _this.options.mindelay;
150
+ _this._disconnectionReason = 'broken';
151
+ return _this.handlers.connected(protocol);
152
+ },
153
+ error: function(e) {
154
+ _this.handlers.error(e);
155
+ return _this._closeOnError();
156
+ },
157
+ message: function(message) {
158
+ return _this.handlers.message(message);
159
+ }
160
+ });
161
+ this._handshakeTimeout = new Timer(function() {
162
+ if (!_this._isSocketConnected()) {
163
+ return;
164
+ }
165
+ _this._disconnectionReason = 'handshake-timeout';
166
+ return _this.socket.close();
167
+ });
168
+ this._reconnectTimer = new Timer(function() {
169
+ if (!_this._connectionDesired) {
170
+ return;
171
+ }
172
+ return _this.connect();
173
+ });
174
+ this.connect();
175
+ }
176
+
177
+ Connector.prototype._isSocketConnected = function() {
178
+ return this.socket && this.socket.readyState === this.WebSocket.OPEN;
179
+ };
180
+
181
+ Connector.prototype.connect = function() {
182
+ var _this = this;
183
+ this._connectionDesired = true;
184
+ if (this._isSocketConnected()) {
185
+ return;
186
+ }
187
+ this._reconnectTimer.stop();
188
+ this._disconnectionReason = 'cannot-connect';
189
+ this.protocolParser.reset();
190
+ this.handlers.connecting();
191
+ this.socket = new this.WebSocket(this._uri);
192
+ this.socket.onopen = function(e) {
193
+ return _this._onopen(e);
194
+ };
195
+ this.socket.onclose = function(e) {
196
+ return _this._onclose(e);
197
+ };
198
+ this.socket.onmessage = function(e) {
199
+ return _this._onmessage(e);
200
+ };
201
+ return this.socket.onerror = function(e) {
202
+ return _this._onerror(e);
203
+ };
204
+ };
205
+
206
+ Connector.prototype.disconnect = function() {
207
+ this._connectionDesired = false;
208
+ this._reconnectTimer.stop();
209
+ if (!this._isSocketConnected()) {
210
+ return;
211
+ }
212
+ this._disconnectionReason = 'manual';
213
+ return this.socket.close();
214
+ };
215
+
216
+ Connector.prototype._scheduleReconnection = function() {
217
+ if (!this._connectionDesired) {
218
+ return;
219
+ }
220
+ if (!this._reconnectTimer.running) {
221
+ this._reconnectTimer.start(this._nextDelay);
222
+ return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2);
223
+ }
224
+ };
225
+
226
+ Connector.prototype.sendCommand = function(command) {
227
+ if (this.protocol == null) {
228
+ return;
229
+ }
230
+ return this._sendCommand(command);
231
+ };
232
+
233
+ Connector.prototype._sendCommand = function(command) {
234
+ return this.socket.send(JSON.stringify(command));
235
+ };
236
+
237
+ Connector.prototype._closeOnError = function() {
238
+ this._handshakeTimeout.stop();
239
+ this._disconnectionReason = 'error';
240
+ return this.socket.close();
241
+ };
242
+
243
+ Connector.prototype._onopen = function(e) {
244
+ var hello;
245
+ this.handlers.socketConnected();
246
+ this._disconnectionReason = 'handshake-failed';
247
+ hello = {
248
+ command: 'hello',
249
+ protocols: [PROTOCOL_6, PROTOCOL_7]
250
+ };
251
+ hello.ver = Version;
252
+ if (this.options.ext) {
253
+ hello.ext = this.options.ext;
254
+ }
255
+ if (this.options.extver) {
256
+ hello.extver = this.options.extver;
257
+ }
258
+ if (this.options.snipver) {
259
+ hello.snipver = this.options.snipver;
260
+ }
261
+ this._sendCommand(hello);
262
+ return this._handshakeTimeout.start(this.options.handshake_timeout);
263
+ };
264
+
265
+ Connector.prototype._onclose = function(e) {
266
+ this.protocol = 0;
267
+ this.handlers.disconnected(this._disconnectionReason, this._nextDelay);
268
+ return this._scheduleReconnection();
269
+ };
270
+
271
+ Connector.prototype._onerror = function(e) {};
272
+
273
+ Connector.prototype._onmessage = function(e) {
274
+ return this.protocolParser.process(e.data);
275
+ };
276
+
277
+ return Connector;
278
+
279
+ })();
280
+
281
+ // timer
282
+ var Timer;
283
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
284
+ __timer.Timer = Timer = (function() {
285
+ function Timer(func) {
286
+ this.func = func;
287
+ this.running = false;
288
+ this.id = null;
289
+ this._handler = __bind(function() {
290
+ this.running = false;
291
+ this.id = null;
292
+ return this.func();
293
+ }, this);
294
+ }
295
+ Timer.prototype.start = function(timeout) {
296
+ if (this.running) {
297
+ clearTimeout(this.id);
298
+ }
299
+ this.id = setTimeout(this._handler, timeout);
300
+ return this.running = true;
301
+ };
302
+ Timer.prototype.stop = function() {
303
+ if (this.running) {
304
+ clearTimeout(this.id);
305
+ this.running = false;
306
+ return this.id = null;
307
+ }
308
+ };
309
+ return Timer;
310
+ })();
311
+ Timer.start = function(timeout, func) {
312
+ return setTimeout(func, timeout);
313
+ };
314
+
315
+ // options
316
+ var Options;
317
+ __options.Options = Options = (function() {
318
+ function Options() {
319
+ this.host = null;
320
+ this.port = 35729;
321
+ this.snipver = null;
322
+ this.ext = null;
323
+ this.extver = null;
324
+ this.mindelay = 1000;
325
+ this.maxdelay = 60000;
326
+ this.handshake_timeout = 5000;
327
+ }
328
+ Options.prototype.set = function(name, value) {
329
+ switch (typeof this[name]) {
330
+ case 'undefined':
331
+ break;
332
+ case 'number':
333
+ return this[name] = +value;
334
+ default:
335
+ return this[name] = value;
336
+ }
337
+ };
338
+ return Options;
339
+ })();
340
+ Options.extract = function(document) {
341
+ var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len2, _ref, _ref2;
342
+ _ref = document.getElementsByTagName('script');
343
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
344
+ element = _ref[_i];
345
+ if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) {
346
+ options = new Options();
347
+ if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) {
348
+ options.host = mm[1];
349
+ if (mm[2]) {
350
+ options.port = parseInt(mm[2], 10);
351
+ }
352
+ }
353
+ if (m[2]) {
354
+ _ref2 = m[2].split('&');
355
+ for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
356
+ pair = _ref2[_j];
357
+ if ((keyAndValue = pair.split('=')).length > 1) {
358
+ options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('='));
359
+ }
360
+ }
361
+ }
362
+ return options;
363
+ }
364
+ }
365
+ return null;
366
+ };
367
+
368
+ // reloader
369
+ // Generated by CoffeeScript 1.3.1
370
+ (function() {
371
+ var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl;
372
+
373
+ splitUrl = function(url) {
374
+ var hash, index, params;
375
+ if ((index = url.indexOf('#')) >= 0) {
376
+ hash = url.slice(index);
377
+ url = url.slice(0, index);
378
+ } else {
379
+ hash = '';
380
+ }
381
+ if ((index = url.indexOf('?')) >= 0) {
382
+ params = url.slice(index);
383
+ url = url.slice(0, index);
384
+ } else {
385
+ params = '';
386
+ }
387
+ return {
388
+ url: url,
389
+ params: params,
390
+ hash: hash
391
+ };
392
+ };
393
+
394
+ pathFromUrl = function(url) {
395
+ var path;
396
+ url = splitUrl(url).url;
397
+ if (url.indexOf('file://') === 0) {
398
+ path = url.replace(/^file:\/\/(localhost)?/, '');
399
+ } else {
400
+ path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/');
401
+ }
402
+ return decodeURIComponent(path);
403
+ };
404
+
405
+ pickBestMatch = function(path, objects, pathFunc) {
406
+ var bestMatch, object, score, _i, _len;
407
+ bestMatch = {
408
+ score: 0
409
+ };
410
+ for (_i = 0, _len = objects.length; _i < _len; _i++) {
411
+ object = objects[_i];
412
+ score = numberOfMatchingSegments(path, pathFunc(object));
413
+ if (score > bestMatch.score) {
414
+ bestMatch = {
415
+ object: object,
416
+ score: score
417
+ };
418
+ }
419
+ }
420
+ if (bestMatch.score > 0) {
421
+ return bestMatch;
422
+ } else {
423
+ return null;
424
+ }
425
+ };
426
+
427
+ numberOfMatchingSegments = function(path1, path2) {
428
+ var comps1, comps2, eqCount, len;
429
+ path1 = path1.replace(/^\/+/, '').toLowerCase();
430
+ path2 = path2.replace(/^\/+/, '').toLowerCase();
431
+ if (path1 === path2) {
432
+ return 10000;
433
+ }
434
+ comps1 = path1.split('/').reverse();
435
+ comps2 = path2.split('/').reverse();
436
+ len = Math.min(comps1.length, comps2.length);
437
+ eqCount = 0;
438
+ while (eqCount < len && comps1[eqCount] === comps2[eqCount]) {
439
+ ++eqCount;
440
+ }
441
+ return eqCount;
442
+ };
443
+
444
+ pathsMatch = function(path1, path2) {
445
+ return numberOfMatchingSegments(path1, path2) > 0;
446
+ };
447
+
448
+ IMAGE_STYLES = [
449
+ {
450
+ selector: 'background',
451
+ styleNames: ['backgroundImage']
452
+ }, {
453
+ selector: 'border',
454
+ styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage']
455
+ }
456
+ ];
457
+
458
+ __reloader.Reloader = Reloader = (function() {
459
+
460
+ Reloader.name = 'Reloader';
461
+
462
+ function Reloader(window, console, Timer) {
463
+ this.window = window;
464
+ this.console = console;
465
+ this.Timer = Timer;
466
+ this.document = this.window.document;
467
+ this.importCacheWaitPeriod = 200;
468
+ this.plugins = [];
469
+ }
470
+
471
+ Reloader.prototype.addPlugin = function(plugin) {
472
+ return this.plugins.push(plugin);
473
+ };
474
+
475
+ Reloader.prototype.analyze = function(callback) {
476
+ return results;
477
+ };
478
+
479
+ Reloader.prototype.reload = function(path, options) {
480
+ var plugin, _base, _i, _len, _ref;
481
+ this.options = options;
482
+ if ((_base = this.options).stylesheetReloadTimeout == null) {
483
+ _base.stylesheetReloadTimeout = 15000;
484
+ }
485
+ _ref = this.plugins;
486
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
487
+ plugin = _ref[_i];
488
+ if (plugin.reload && plugin.reload(path, options)) {
489
+ return;
490
+ }
491
+ }
492
+ if (options.liveCSS) {
493
+ if (path.match(/\.css$/i)) {
494
+ if (this.reloadStylesheet(path)) {
495
+ return;
496
+ }
497
+ }
498
+ }
499
+ if (options.liveImg) {
500
+ if (path.match(/\.(jpe?g|png|gif)$/i)) {
501
+ this.reloadImages(path);
502
+ return;
503
+ }
504
+ }
505
+ return this.reloadPage();
506
+ };
507
+
508
+ Reloader.prototype.reloadPage = function() {
509
+ return this.window.document.location.reload();
510
+ };
511
+
512
+ Reloader.prototype.reloadImages = function(path) {
513
+ var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results;
514
+ expando = this.generateUniqueString();
515
+ _ref = this.document.images;
516
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
517
+ img = _ref[_i];
518
+ if (pathsMatch(path, pathFromUrl(img.src))) {
519
+ img.src = this.generateCacheBustUrl(img.src, expando);
520
+ }
521
+ }
522
+ if (this.document.querySelectorAll) {
523
+ for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) {
524
+ _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames;
525
+ _ref2 = this.document.querySelectorAll("[style*=" + selector + "]");
526
+ for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
527
+ img = _ref2[_k];
528
+ this.reloadStyleImages(img.style, styleNames, path, expando);
529
+ }
530
+ }
531
+ }
532
+ if (this.document.styleSheets) {
533
+ _ref3 = this.document.styleSheets;
534
+ _results = [];
535
+ for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
536
+ styleSheet = _ref3[_l];
537
+ _results.push(this.reloadStylesheetImages(styleSheet, path, expando));
538
+ }
539
+ return _results;
540
+ }
541
+ };
542
+
543
+ Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) {
544
+ var rule, rules, styleNames, _i, _j, _len, _len1;
545
+ try {
546
+ rules = styleSheet != null ? styleSheet.cssRules : void 0;
547
+ } catch (e) {
548
+
549
+ }
550
+ if (!rules) {
551
+ return;
552
+ }
553
+ for (_i = 0, _len = rules.length; _i < _len; _i++) {
554
+ rule = rules[_i];
555
+ switch (rule.type) {
556
+ case CSSRule.IMPORT_RULE:
557
+ this.reloadStylesheetImages(rule.styleSheet, path, expando);
558
+ break;
559
+ case CSSRule.STYLE_RULE:
560
+ for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) {
561
+ styleNames = IMAGE_STYLES[_j].styleNames;
562
+ this.reloadStyleImages(rule.style, styleNames, path, expando);
563
+ }
564
+ break;
565
+ case CSSRule.MEDIA_RULE:
566
+ this.reloadStylesheetImages(rule, path, expando);
567
+ }
568
+ }
569
+ };
570
+
571
+ Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) {
572
+ var newValue, styleName, value, _i, _len,
573
+ _this = this;
574
+ for (_i = 0, _len = styleNames.length; _i < _len; _i++) {
575
+ styleName = styleNames[_i];
576
+ value = style[styleName];
577
+ if (typeof value === 'string') {
578
+ newValue = value.replace(/\burl\s*\(([^)]*)\)/, function(match, src) {
579
+ if (pathsMatch(path, pathFromUrl(src))) {
580
+ return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")";
581
+ } else {
582
+ return match;
583
+ }
584
+ });
585
+ if (newValue !== value) {
586
+ style[styleName] = newValue;
587
+ }
588
+ }
589
+ }
590
+ };
591
+
592
+ Reloader.prototype.reloadStylesheet = function(path) {
593
+ var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1,
594
+ _this = this;
595
+ links = (function() {
596
+ var _i, _len, _ref, _results;
597
+ _ref = this.document.getElementsByTagName('link');
598
+ _results = [];
599
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
600
+ link = _ref[_i];
601
+ if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) {
602
+ _results.push(link);
603
+ }
604
+ }
605
+ return _results;
606
+ }).call(this);
607
+ imported = [];
608
+ _ref = this.document.getElementsByTagName('style');
609
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
610
+ style = _ref[_i];
611
+ if (style.sheet) {
612
+ this.collectImportedStylesheets(style, style.sheet, imported);
613
+ }
614
+ }
615
+ for (_j = 0, _len1 = links.length; _j < _len1; _j++) {
616
+ link = links[_j];
617
+ this.collectImportedStylesheets(link, link.sheet, imported);
618
+ }
619
+ if (this.window.StyleFix && this.document.querySelectorAll) {
620
+ _ref1 = this.document.querySelectorAll('style[data-href]');
621
+ for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
622
+ style = _ref1[_k];
623
+ links.push(style);
624
+ }
625
+ }
626
+ this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets");
627
+ match = pickBestMatch(path, links.concat(imported), function(l) {
628
+ return pathFromUrl(_this.linkHref(l));
629
+ });
630
+ if (match) {
631
+ if (match.object.rule) {
632
+ this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href);
633
+ this.reattachImportedRule(match.object);
634
+ } else {
635
+ this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object)));
636
+ this.reattachStylesheetLink(match.object);
637
+ }
638
+ } else {
639
+ this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one");
640
+ for (_l = 0, _len3 = links.length; _l < _len3; _l++) {
641
+ link = links[_l];
642
+ this.reattachStylesheetLink(link);
643
+ }
644
+ }
645
+ return true;
646
+ };
647
+
648
+ Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) {
649
+ var index, rule, rules, _i, _len;
650
+ try {
651
+ rules = styleSheet != null ? styleSheet.cssRules : void 0;
652
+ } catch (e) {
653
+
654
+ }
655
+ if (rules && rules.length) {
656
+ for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) {
657
+ rule = rules[index];
658
+ switch (rule.type) {
659
+ case CSSRule.CHARSET_RULE:
660
+ continue;
661
+ case CSSRule.IMPORT_RULE:
662
+ result.push({
663
+ link: link,
664
+ rule: rule,
665
+ index: index,
666
+ href: rule.href
667
+ });
668
+ this.collectImportedStylesheets(link, rule.styleSheet, result);
669
+ break;
670
+ default:
671
+ break;
672
+ }
673
+ }
674
+ }
675
+ };
676
+
677
+ Reloader.prototype.waitUntilCssLoads = function(clone, func) {
678
+ var callbackExecuted, executeCallback, poll,
679
+ _this = this;
680
+ callbackExecuted = false;
681
+ executeCallback = function() {
682
+ if (callbackExecuted) {
683
+ return;
684
+ }
685
+ callbackExecuted = true;
686
+ return func();
687
+ };
688
+ clone.onload = function() {
689
+ console.log("onload!");
690
+ _this.knownToSupportCssOnLoad = true;
691
+ return executeCallback();
692
+ };
693
+ if (!this.knownToSupportCssOnLoad) {
694
+ (poll = function() {
695
+ if (clone.sheet) {
696
+ console.log("polling!");
697
+ return executeCallback();
698
+ } else {
699
+ return _this.Timer.start(50, poll);
700
+ }
701
+ })();
702
+ }
703
+ return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback);
704
+ };
705
+
706
+ Reloader.prototype.linkHref = function(link) {
707
+ return link.href || link.getAttribute('data-href');
708
+ };
709
+
710
+ Reloader.prototype.reattachStylesheetLink = function(link) {
711
+ var clone, parent,
712
+ _this = this;
713
+ if (link.__LiveReload_pendingRemoval) {
714
+ return;
715
+ }
716
+ link.__LiveReload_pendingRemoval = true;
717
+ if (link.tagName === 'STYLE') {
718
+ clone = this.document.createElement('link');
719
+ clone.rel = 'stylesheet';
720
+ clone.media = link.media;
721
+ clone.disabled = link.disabled;
722
+ } else {
723
+ clone = link.cloneNode(false);
724
+ }
725
+ clone.href = this.generateCacheBustUrl(this.linkHref(link));
726
+ parent = link.parentNode;
727
+ if (parent.lastChild === link) {
728
+ parent.appendChild(clone);
729
+ } else {
730
+ parent.insertBefore(clone, link.nextSibling);
731
+ }
732
+ return this.waitUntilCssLoads(clone, function() {
733
+ var additionalWaitingTime;
734
+ if (/AppleWebKit/.test(navigator.userAgent)) {
735
+ additionalWaitingTime = 5;
736
+ } else {
737
+ additionalWaitingTime = 200;
738
+ }
739
+ return _this.Timer.start(additionalWaitingTime, function() {
740
+ var _ref;
741
+ if (!link.parentNode) {
742
+ return;
743
+ }
744
+ link.parentNode.removeChild(link);
745
+ clone.onreadystatechange = null;
746
+ return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0;
747
+ });
748
+ });
749
+ };
750
+
751
+ Reloader.prototype.reattachImportedRule = function(_arg) {
752
+ var href, index, link, media, newRule, parent, rule, tempLink,
753
+ _this = this;
754
+ rule = _arg.rule, index = _arg.index, link = _arg.link;
755
+ parent = rule.parentStyleSheet;
756
+ href = this.generateCacheBustUrl(rule.href);
757
+ media = rule.media.length ? [].join.call(rule.media, ', ') : '';
758
+ newRule = "@import url(\"" + href + "\") " + media + ";";
759
+ rule.__LiveReload_newHref = href;
760
+ tempLink = this.document.createElement("link");
761
+ tempLink.rel = 'stylesheet';
762
+ tempLink.href = href;
763
+ tempLink.__LiveReload_pendingRemoval = true;
764
+ if (link.parentNode) {
765
+ link.parentNode.insertBefore(tempLink, link);
766
+ }
767
+ return this.Timer.start(this.importCacheWaitPeriod, function() {
768
+ if (tempLink.parentNode) {
769
+ tempLink.parentNode.removeChild(tempLink);
770
+ }
771
+ if (rule.__LiveReload_newHref !== href) {
772
+ return;
773
+ }
774
+ parent.insertRule(newRule, index);
775
+ parent.deleteRule(index + 1);
776
+ rule = parent.cssRules[index];
777
+ rule.__LiveReload_newHref = href;
778
+ return _this.Timer.start(_this.importCacheWaitPeriod, function() {
779
+ if (rule.__LiveReload_newHref !== href) {
780
+ return;
781
+ }
782
+ parent.insertRule(newRule, index);
783
+ return parent.deleteRule(index + 1);
784
+ });
785
+ });
786
+ };
787
+
788
+ Reloader.prototype.generateUniqueString = function() {
789
+ return 'livereload=' + Date.now();
790
+ };
791
+
792
+ Reloader.prototype.generateCacheBustUrl = function(url, expando) {
793
+ var hash, oldParams, params, _ref;
794
+ if (expando == null) {
795
+ expando = this.generateUniqueString();
796
+ }
797
+ _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params;
798
+ if (this.options.overrideURL) {
799
+ if (url.indexOf(this.options.serverURL) < 0) {
800
+ url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url);
801
+ }
802
+ }
803
+ params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) {
804
+ return "" + sep + expando;
805
+ });
806
+ if (params === oldParams) {
807
+ if (oldParams.length === 0) {
808
+ params = "?" + expando;
809
+ } else {
810
+ params = "" + oldParams + "&" + expando;
811
+ }
812
+ }
813
+ return url + params + hash;
814
+ };
815
+
816
+ return Reloader;
817
+
818
+ })();
819
+
820
+ }).call(this);
821
+
822
+ // livereload
823
+ var Connector, LiveReload, Options, Reloader, Timer;
824
+
825
+ Connector = __connector.Connector;
826
+
827
+ Timer = __timer.Timer;
828
+
829
+ Options = __options.Options;
830
+
831
+ Reloader = __reloader.Reloader;
832
+
833
+ __livereload.LiveReload = LiveReload = (function() {
834
+
835
+ function LiveReload(window) {
836
+ var _this = this;
837
+ this.window = window;
838
+ this.listeners = {};
839
+ this.plugins = [];
840
+ this.pluginIdentifiers = {};
841
+ this.console = this.window.location.href.match(/LR-verbose/) && this.window.console && this.window.console.log && this.window.console.error ? this.window.console : {
842
+ log: function() {},
843
+ error: function() {}
844
+ };
845
+ if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) {
846
+ console.error("LiveReload disabled because the browser does not seem to support web sockets");
847
+ return;
848
+ }
849
+ if (!(this.options = Options.extract(this.window.document))) {
850
+ console.error("LiveReload disabled because it could not find its own <SCRIPT> tag");
851
+ return;
852
+ }
853
+ this.reloader = new Reloader(this.window, this.console, Timer);
854
+ this.connector = new Connector(this.options, this.WebSocket, Timer, {
855
+ connecting: function() {},
856
+ socketConnected: function() {},
857
+ connected: function(protocol) {
858
+ var _base;
859
+ if (typeof (_base = _this.listeners).connect === "function") {
860
+ _base.connect();
861
+ }
862
+ _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ").");
863
+ return _this.analyze();
864
+ },
865
+ error: function(e) {
866
+ if (e instanceof ProtocolError) {
867
+ return console.log("" + e.message + ".");
868
+ } else {
869
+ return console.log("LiveReload internal error: " + e.message);
870
+ }
871
+ },
872
+ disconnected: function(reason, nextDelay) {
873
+ var _base;
874
+ if (typeof (_base = _this.listeners).disconnect === "function") {
875
+ _base.disconnect();
876
+ }
877
+ switch (reason) {
878
+ case 'cannot-connect':
879
+ return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec.");
880
+ case 'broken':
881
+ return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec.");
882
+ case 'handshake-timeout':
883
+ return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec.");
884
+ case 'handshake-failed':
885
+ return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec.");
886
+ case 'manual':
887
+ break;
888
+ case 'error':
889
+ break;
890
+ default:
891
+ return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec.");
892
+ }
893
+ },
894
+ message: function(message) {
895
+ switch (message.command) {
896
+ case 'reload':
897
+ return _this.performReload(message);
898
+ case 'alert':
899
+ return _this.performAlert(message);
900
+ }
901
+ }
902
+ });
903
+ }
904
+
905
+ LiveReload.prototype.on = function(eventName, handler) {
906
+ return this.listeners[eventName] = handler;
907
+ };
908
+
909
+ LiveReload.prototype.log = function(message) {
910
+ return this.console.log("" + message);
911
+ };
912
+
913
+ LiveReload.prototype.performReload = function(message) {
914
+ var _ref, _ref2;
915
+ this.log("LiveReload received reload request for " + message.path + ".");
916
+ return this.reloader.reload(message.path, {
917
+ liveCSS: (_ref = message.liveCSS) != null ? _ref : true,
918
+ liveImg: (_ref2 = message.liveImg) != null ? _ref2 : true,
919
+ originalPath: message.originalPath || '',
920
+ overrideURL: message.overrideURL || '',
921
+ serverURL: "http://" + this.options.host + ":" + this.options.port
922
+ });
923
+ };
924
+
925
+ LiveReload.prototype.performAlert = function(message) {
926
+ return alert(message.message);
927
+ };
928
+
929
+ LiveReload.prototype.shutDown = function() {
930
+ var _base;
931
+ this.connector.disconnect();
932
+ this.log("LiveReload disconnected.");
933
+ return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0;
934
+ };
935
+
936
+ LiveReload.prototype.hasPlugin = function(identifier) {
937
+ return !!this.pluginIdentifiers[identifier];
938
+ };
939
+
940
+ LiveReload.prototype.addPlugin = function(pluginClass) {
941
+ var plugin;
942
+ var _this = this;
943
+ if (this.hasPlugin(pluginClass.identifier)) return;
944
+ this.pluginIdentifiers[pluginClass.identifier] = true;
945
+ plugin = new pluginClass(this.window, {
946
+ _livereload: this,
947
+ _reloader: this.reloader,
948
+ _connector: this.connector,
949
+ console: this.console,
950
+ Timer: Timer,
951
+ generateCacheBustUrl: function(url) {
952
+ return _this.reloader.generateCacheBustUrl(url);
953
+ }
954
+ });
955
+ this.plugins.push(plugin);
956
+ this.reloader.addPlugin(plugin);
957
+ };
958
+
959
+ LiveReload.prototype.analyze = function() {
960
+ var plugin, pluginData, pluginsData, _i, _len, _ref;
961
+ if (!(this.connector.protocol >= 7)) return;
962
+ pluginsData = {};
963
+ _ref = this.plugins;
964
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
965
+ plugin = _ref[_i];
966
+ pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {};
967
+ pluginData.version = plugin.constructor.version;
968
+ }
969
+ this.connector.sendCommand({
970
+ command: 'info',
971
+ plugins: pluginsData,
972
+ url: this.window.location.href
973
+ });
974
+ };
975
+
976
+ return LiveReload;
977
+
978
+ })();
979
+
980
+ // less
981
+ var LessPlugin;
982
+ __less = LessPlugin = (function() {
983
+ LessPlugin.identifier = 'less';
984
+ LessPlugin.version = '1.0';
985
+ function LessPlugin(window, host) {
986
+ this.window = window;
987
+ this.host = host;
988
+ }
989
+ LessPlugin.prototype.reload = function(path, options) {
990
+ if (this.window.less && this.window.less.refresh) {
991
+ if (path.match(/\.less$/i)) {
992
+ return this.reloadLess(path);
993
+ }
994
+ if (options.originalPath.match(/\.less$/i)) {
995
+ return this.reloadLess(options.originalPath);
996
+ }
997
+ }
998
+ return false;
999
+ };
1000
+ LessPlugin.prototype.reloadLess = function(path) {
1001
+ var link, links, _i, _len;
1002
+ links = (function() {
1003
+ var _i, _len, _ref, _results;
1004
+ _ref = document.getElementsByTagName('link');
1005
+ _results = [];
1006
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1007
+ link = _ref[_i];
1008
+ if (link.href && link.rel === 'stylesheet/less' || (link.rel.match(/stylesheet/) && link.type.match(/^text\/(x-)?less$/))) {
1009
+ _results.push(link);
1010
+ }
1011
+ }
1012
+ return _results;
1013
+ })();
1014
+ if (links.length === 0) {
1015
+ return false;
1016
+ }
1017
+ for (_i = 0, _len = links.length; _i < _len; _i++) {
1018
+ link = links[_i];
1019
+ link.href = this.host.generateCacheBustUrl(link.href);
1020
+ }
1021
+ this.host.console.log("LiveReload is asking LESS to recompile all stylesheets");
1022
+ this.window.less.refresh(true);
1023
+ return true;
1024
+ };
1025
+ LessPlugin.prototype.analyze = function() {
1026
+ return {
1027
+ disable: !!(this.window.less && this.window.less.refresh)
1028
+ };
1029
+ };
1030
+ return LessPlugin;
1031
+ })();
1032
+
1033
+ // startup
1034
+ var CustomEvents, LiveReload, k;
1035
+ CustomEvents = __customevents;
1036
+ LiveReload = window.LiveReload = new (__livereload.LiveReload)(window);
1037
+ for (k in window) {
1038
+ if (k.match(/^LiveReloadPlugin/)) {
1039
+ LiveReload.addPlugin(window[k]);
1040
+ }
1041
+ }
1042
+ LiveReload.addPlugin(__less);
1043
+ LiveReload.on('shutdown', function() {
1044
+ return delete window.LiveReload;
1045
+ });
1046
+ LiveReload.on('connect', function() {
1047
+ return CustomEvents.fire(document, 'LiveReloadConnect');
1048
+ });
1049
+ LiveReload.on('disconnect', function() {
1050
+ return CustomEvents.fire(document, 'LiveReloadDisconnect');
1051
+ });
1052
+ CustomEvents.bind(document, 'LiveReloadShutDown', function() {
1053
+ return LiveReload.shutDown();
1054
+ });
1055
+ })();