rack-livereload 0.3.13 → 0.3.14

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  <a href="http://travis-ci.org/johnbintz/rack-livereload"><img src="https://secure.travis-ci.org/johnbintz/rack-livereload.png" /></a>
2
+ [![Code Climate](https://codeclimate.com/github/johnbintz/rack-livereload.png)](https://codeclimate.com/github/johnbintz/rack-livereload)
2
3
 
3
4
  Hey, you've got [LiveReload](http://www.livereload.com/) in my [Rack](http://rack.rubyforge.org/)!
4
5
  No need for browser extensions anymore! Just plug it in your middleware stack and go!
@@ -1,6 +1,6 @@
1
1
  require "rack/livereload"
2
2
 
3
3
  class Rack::LiveReload
4
- VERSION = '0.3.13'
4
+ VERSION = '0.3.14'
5
5
  end
6
6
 
@@ -1,50 +1,13 @@
1
1
  require 'erb'
2
+ require 'rack/livereload/processing_skip_analyzer'
3
+ require 'rack/livereload/body_processor'
2
4
 
3
5
  module Rack
4
6
  class LiveReload
5
- LIVERELOAD_JS_PATH = '/__rack/livereload.js'
6
- HEAD_TAG_REGEX = /<head>|<head[^(er)][^<]*>/
7
-
8
- BAD_USER_AGENTS = [ %r{MSIE} ]
9
-
10
- def livereload_local_uri
11
- "http://localhost:#{@port}/livereload.js"
12
- end
13
-
14
7
  attr_reader :app
15
8
 
16
9
  def initialize(app, options = {})
17
10
  @app, @options = app, options
18
- @port = @options[:live_reload_port] || 35729
19
- end
20
-
21
- def use_vendored?
22
- return @use_vendored if @use_vendored
23
-
24
- if @options[:source]
25
- @use_vendored = (@options[:source] == :vendored)
26
- else
27
- require 'net/http'
28
- require 'uri'
29
-
30
-
31
- uri = URI.parse(livereload_local_uri)
32
-
33
- http = Net::HTTP.new(uri.host, uri.port)
34
- http.read_timeout = 1
35
-
36
- begin
37
- http.send_request('GET', uri.path)
38
- @use_vendored = false
39
- rescue Timeout::Error, Errno::ECONNREFUSED, EOFError
40
- @use_vendored = true
41
- rescue => e
42
- $stderr.puts e.inspect
43
- raise e
44
- end
45
- end
46
-
47
- @use_vendored
48
11
  end
49
12
 
50
13
  def call(env)
@@ -59,62 +22,21 @@ module Rack
59
22
  else
60
23
  status, headers, body = result = @app.call(env)
61
24
 
62
- if (headers['Content-Type'] and headers['Content-Type']['text/event-stream']) or
63
- headers['Transfer-Encoding'] == 'chunked' or
64
- headers['Content-Disposition'] =~ %r{^inline}
65
- return result
66
- end
67
-
68
- body.close if body.respond_to?(:close)
69
-
70
- new_body = [] ; body.each { |line| new_body << line.to_s }
71
-
72
- if !ignored?(env['PATH_INFO']) and !bad_browser?(env['HTTP_USER_AGENT'])
73
- if headers['Content-Type'] and status == 200 and headers['Content-Type'][%r{text/html}]
74
- content_length = 0
75
-
76
- new_body.each do |line|
77
- if !headers['X-Rack-LiveReload'] && line['<head']
78
- host_to_use = (@options[:host] || env['HTTP_HOST'] || 'localhost').gsub(%r{:.*}, '')
79
-
80
- if use_vendored?
81
- src = LIVERELOAD_JS_PATH.dup + "?host=#{host_to_use}"
82
- else
83
- src = livereload_local_uri.dup.gsub('localhost', host_to_use) + '?'
84
- end
85
-
86
- src << "&amp;mindelay=#{@options[:min_delay]}" if @options[:min_delay]
87
- src << "&amp;maxdelay=#{@options[:max_delay]}" if @options[:max_delay]
88
- src << "&amp;port=#{@options[:port]}" if @options[:port]
89
-
90
- template = ERB.new(::File.read(::File.expand_path('../../../skel/livereload.html.erb', __FILE__)))
91
-
92
- if line['<head']
93
- line.gsub!(HEAD_TAG_REGEX) { |match| %{#{match}#{template.result(binding)}} }
94
- end
25
+ return result if ProcessingSkipAnalyzer.skip_processing?(result, env, @options)
95
26
 
96
- headers["X-Rack-LiveReload"] = '1'
97
- end
27
+ processor = BodyProcessor.new(body, @options)
28
+ processor.process!(env)
98
29
 
99
- content_length += line.bytesize
100
- end
30
+ headers['Content-Length'] = processor.content_length.to_s
101
31
 
102
- headers['Content-Length'] = content_length.to_s
103
- end
32
+ if processor.livereload_added
33
+ headers['X-Rack-LiveReload'] = '1'
104
34
  end
105
35
 
106
- [ status, headers, new_body ]
36
+ [ status, headers, processor.new_body ]
107
37
  end
108
38
  end
109
39
 
110
- def ignored?(path_info)
111
- @options[:ignore] and @options[:ignore].any? { |filter| path_info[filter] }
112
- end
113
-
114
- def bad_browser?(user_agent)
115
- BAD_USER_AGENTS.any? { |pattern| (user_agent || '')[pattern] }
116
- end
117
-
118
40
  private
119
41
  def deliver_file(file)
120
42
  type = case ::File.extname(file)
@@ -126,14 +48,6 @@ module Rack
126
48
 
127
49
  [ 200, { 'Content-Type' => type, 'Content-Length' => ::File.size(file).to_s }, [ ::File.read(file) ] ]
128
50
  end
129
-
130
- def force_swf?
131
- @options[:force_swf]
132
- end
133
-
134
- def with_swf?
135
- !@options[:no_swf]
136
- end
137
51
  end
138
52
  end
139
53
 
@@ -0,0 +1,112 @@
1
+ require 'rack/livereload'
2
+
3
+ module Rack
4
+ class LiveReload
5
+ class BodyProcessor
6
+ LIVERELOAD_JS_PATH = '/__rack/livereload.js'
7
+ HEAD_TAG_REGEX = /<head>|<head[^(er)][^<]*>/
8
+ LIVERELOAD_PORT = 35729
9
+
10
+ attr_reader :content_length, :new_body, :livereload_added
11
+
12
+ def livereload_local_uri
13
+ "http://localhost:#{@options[:live_reload_port]}/livereload.js"
14
+ end
15
+
16
+ def initialize(body, options)
17
+ @body, @options = body, options
18
+ @options[:live_reload_port] ||= LIVERELOAD_PORT
19
+
20
+ @processed = false
21
+ end
22
+
23
+ def force_swf?
24
+ @options[:force_swf]
25
+ end
26
+
27
+ def with_swf?
28
+ !@options[:no_swf]
29
+ end
30
+
31
+ def use_vendored?
32
+ return @use_vendored if @use_vendored
33
+
34
+ if @options[:source]
35
+ @use_vendored = (@options[:source] == :vendored)
36
+ else
37
+ require 'net/http'
38
+ require 'uri'
39
+
40
+ uri = URI.parse(livereload_local_uri)
41
+
42
+ http = Net::HTTP.new(uri.host, uri.port)
43
+ http.read_timeout = 1
44
+
45
+ begin
46
+ http.send_request('GET', uri.path)
47
+ @use_vendored = false
48
+ rescue Timeout::Error, Errno::ECONNREFUSED, EOFError
49
+ @use_vendored = true
50
+ rescue => e
51
+ $stderr.puts e.inspect
52
+ raise e
53
+ end
54
+ end
55
+
56
+ @use_vendored
57
+ end
58
+
59
+ def processed?
60
+ @processed
61
+ end
62
+
63
+ def process!(env)
64
+ @env = env
65
+ @body.close if @body.respond_to?(:close)
66
+
67
+ @new_body = [] ; @body.each { |line| @new_body << line.to_s }
68
+
69
+ @content_length = 0
70
+ @livereload_added = false
71
+
72
+ @new_body.each do |line|
73
+ if !@livereload_added && line['<head']
74
+ line.gsub!(HEAD_TAG_REGEX) { |match| %{#{match}#{template.result(binding)}} }
75
+
76
+ @livereload_added = true
77
+ end
78
+
79
+ @content_length += line.bytesize
80
+ @processed = true
81
+ end
82
+ end
83
+
84
+ def app_root
85
+ ENV['RAILS_RELATIVE_URL_ROOT'] || ''
86
+ end
87
+
88
+ def host_to_use
89
+ (@options[:host] || @env['HTTP_HOST'] || 'localhost').gsub(%r{:.*}, '')
90
+ end
91
+
92
+ def template
93
+ ERB.new(::File.read(::File.expand_path('../../../../skel/livereload.html.erb', __FILE__)))
94
+ end
95
+
96
+ def livereload_source
97
+ if use_vendored?
98
+ src = "#{app_root}#{LIVERELOAD_JS_PATH.dup}?host=#{host_to_use}"
99
+ else
100
+ src = livereload_local_uri.dup.gsub('localhost', host_to_use) + '?'
101
+ end
102
+
103
+ src << "&amp;mindelay=#{@options[:min_delay]}" if @options[:min_delay]
104
+ src << "&amp;maxdelay=#{@options[:max_delay]}" if @options[:max_delay]
105
+ src << "&amp;port=#{@options[:port]}" if @options[:port]
106
+
107
+ src
108
+ end
109
+ end
110
+ end
111
+ end
112
+
@@ -0,0 +1,44 @@
1
+ require 'rack/livereload'
2
+
3
+ module Rack
4
+ class LiveReload
5
+ class ProcessingSkipAnalyzer
6
+ BAD_USER_AGENTS = [ %r{MSIE} ]
7
+
8
+ def self.skip_processing?(result, env, options)
9
+ new(result, env, options).skip_processing?
10
+ end
11
+
12
+ def initialize(result, env, options)
13
+ @env, @options = env, options
14
+
15
+ @status, @headers, @body = result
16
+ end
17
+
18
+ def skip_processing?
19
+ !html? || chunked? || inline? || ignored? || bad_browser?
20
+ end
21
+
22
+ def chunked?
23
+ @headers['Transfer-Encoding'] == 'chunked'
24
+ end
25
+
26
+ def inline?
27
+ @headers['Content-Disposition'] =~ %r{^inline}
28
+ end
29
+
30
+ def ignored?
31
+ @options[:ignore] and @options[:ignore].any? { |filter| @env['PATH_INFO'][filter] }
32
+ end
33
+
34
+ def bad_browser?
35
+ BAD_USER_AGENTS.any? { |pattern| @env['HTTP_USER_AGENT'] =~ pattern }
36
+ end
37
+
38
+ def html?
39
+ @headers['Content-Type'] =~ %r{text/html}
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -5,11 +5,11 @@
5
5
  WEB_SOCKET_FORCE_FLASH = true;
6
6
  <% end %>
7
7
  </script>
8
- <script type="text/javascript" src="/__rack/swfobject.js"></script>
9
- <script type="text/javascript" src="/__rack/web_socket.js"></script>
8
+ <script type="text/javascript" src="<%= app_root %>/__rack/swfobject.js"></script>
9
+ <script type="text/javascript" src="<%= app_root %>/__rack/web_socket.js"></script>
10
10
  <% end %>
11
11
  <script type="text/javascript">
12
- RACK_LIVERELOAD_PORT = <%= @port %>;
12
+ RACK_LIVERELOAD_PORT = <%= @options[:live_reload_port] %>;
13
13
  </script>
14
- <script type="text/javascript" src="<%= src %>"></script>
14
+ <script type="text/javascript" src="<%= livereload_source %>"></script>
15
15
 
@@ -0,0 +1,200 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ describe Rack::LiveReload::BodyProcessor do
5
+ describe 'head tag regex' do
6
+ let(:regex) { described_class::HEAD_TAG_REGEX }
7
+ subject { regex }
8
+
9
+ it { should be_kind_of(Regexp) }
10
+
11
+ it 'only picks a valid <head> tag' do
12
+ regex.match("<head></head>").to_s.should eq('<head>')
13
+ regex.match("<head><title></title></head>").to_s.should eq('<head>')
14
+ regex.match("<head attribute='something'><title></title></head>").to_s.should eq("<head attribute='something'>")
15
+ end
16
+
17
+ it 'responds false when no head tag' do
18
+ regex.match("<header></header>").should be_false
19
+ end
20
+ end
21
+
22
+ let(:processor) { described_class.new(body, options) }
23
+ let(:body) { [ page_html ] }
24
+ let(:options) { {} }
25
+ let(:page_html) { '<head></head>' }
26
+
27
+ let(:processor_result) do
28
+ if !processor.processed?
29
+ processor.process!(env)
30
+ end
31
+
32
+ processor
33
+ end
34
+
35
+ subject { processor }
36
+
37
+ describe "livereload local uri" do
38
+ context 'does not exist' do
39
+ before do
40
+ stub_request(:any, 'localhost:35729/livereload.js').to_timeout
41
+ end
42
+
43
+ it { should use_vendored }
44
+ end
45
+
46
+ context 'exists' do
47
+ before do
48
+ stub_request(:any, 'localhost:35729/livereload.js')
49
+ end
50
+
51
+ it { should_not use_vendored }
52
+ end
53
+
54
+ context 'with custom port' do
55
+ let(:options) { {:live_reload_port => '12348'}}
56
+
57
+ context 'exists' do
58
+ before do
59
+ stub_request(:any, 'localhost:12348/livereload.js')
60
+ end
61
+ it { should_not use_vendored }
62
+ end
63
+ end
64
+
65
+ context 'specify vendored' do
66
+ let(:options) { { :source => :vendored } }
67
+
68
+ it { should use_vendored }
69
+ end
70
+
71
+ context 'specify LR' do
72
+ let(:options) { { :source => :livereload } }
73
+
74
+ it { should_not use_vendored }
75
+ end
76
+ end
77
+
78
+ context 'text/html' do
79
+ before do
80
+ processor.stubs(:use_vendored?).returns(true)
81
+ end
82
+
83
+ let(:host) { 'host' }
84
+ let(:env) { { 'HTTP_HOST' => host } }
85
+
86
+ let(:processed_body) { processor_result.new_body.join('') }
87
+ let(:length) { processor_result.content_length }
88
+
89
+ let(:page_html) { '<head></head>' }
90
+
91
+ context 'vendored' do
92
+ it 'should add the vendored livereload js script tag' do
93
+ processed_body.should include("script")
94
+ processed_body.should include(described_class::LIVERELOAD_JS_PATH)
95
+
96
+ length.to_s.should == processed_body.length.to_s
97
+
98
+ described_class::LIVERELOAD_JS_PATH.should_not include(host)
99
+
100
+ processed_body.should include('swfobject')
101
+ processed_body.should include('web_socket')
102
+ end
103
+ end
104
+
105
+ context 'at the top of the head tag' do
106
+ let(:page_html) { '<head attribute="attribute"><script type="text/javascript" insert="first"></script><script type="text/javascript" insert="before"></script></head>' }
107
+
108
+ let(:body_dom) { Nokogiri::XML(processed_body) }
109
+
110
+ it 'should add the livereload js script tag before all other script tags' do
111
+ body_dom.at_css("head")[:attribute].should == 'attribute'
112
+ body_dom.at_css("script:eq(5)")[:src].should include(described_class::LIVERELOAD_JS_PATH)
113
+ body_dom.at_css("script:last-child")[:insert].should == "before"
114
+ end
115
+
116
+ context 'when a relative URL root is specified' do
117
+ before do
118
+ ENV['RAILS_RELATIVE_URL_ROOT'] = '/a_relative_path'
119
+ end
120
+
121
+ it 'should prepend the relative path to the script src' do
122
+ body_dom.at_css("script:eq(5)")[:src].should match(%r{^/a_relative_path/})
123
+ end
124
+ end
125
+ end
126
+
127
+ describe "LIVERELOAD_PORT value" do
128
+ let(:options) { { :live_reload_port => 12345 }}
129
+
130
+ it "sets the variable at the top of the file" do
131
+ processed_body.should include 'RACK_LIVERELOAD_PORT = 12345'
132
+ end
133
+ end
134
+
135
+ context 'in header tags' do
136
+ let(:page_html) { "<header class='hero'><h1>Just a normal header tag</h1></header>" }
137
+
138
+ let(:body_dom) { Nokogiri::XML(processed_body) }
139
+
140
+ it 'should not add the livereload js' do
141
+ body_dom.at_css("header")[:class].should == 'hero'
142
+ body_dom.css('script').should be_empty
143
+ end
144
+ end
145
+
146
+ context 'not vendored' do
147
+ before do
148
+ processor.stubs(:use_vendored?).returns(false)
149
+ end
150
+
151
+ it 'should add the LR livereload js script tag' do
152
+ processed_body.should include("script")
153
+ processed_body.should include(processor.livereload_local_uri.gsub('localhost', 'host'))
154
+ end
155
+ end
156
+
157
+ context 'set options' do
158
+ let(:options) { { :host => new_host, :port => port, :min_delay => min_delay, :max_delay => max_delay } }
159
+ let(:min_delay) { 5 }
160
+ let(:max_delay) { 10 }
161
+ let(:port) { 23 }
162
+ let(:new_host) { 'myhost' }
163
+
164
+ it 'should add the livereload.js script tag' do
165
+ processed_body.should include("mindelay=#{min_delay}")
166
+ processed_body.should include("maxdelay=#{max_delay}")
167
+ processed_body.should include("port=#{port}")
168
+ processed_body.should include("host=#{new_host}")
169
+ end
170
+ end
171
+
172
+ context 'force flash' do
173
+ let(:options) { { :force_swf => true } }
174
+
175
+ it 'should not add the flash shim' do
176
+ processed_body.should include('WEB_SOCKET_FORCE_FLASH')
177
+ processed_body.should include('swfobject')
178
+ processed_body.should include('web_socket')
179
+ end
180
+ end
181
+
182
+ context 'no flash' do
183
+ let(:options) { { :no_swf => true } }
184
+
185
+ it 'should not add the flash shim' do
186
+ processed_body.should_not include('swfobject')
187
+ processed_body.should_not include('web_socket')
188
+ end
189
+ end
190
+
191
+ context 'no host at all' do
192
+ let(:env) { {} }
193
+
194
+ it 'should use localhost' do
195
+ processed_body.should include('localhost')
196
+ end
197
+ end
198
+ end
199
+ end
200
+
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::LiveReload::ProcessingSkipAnalyzer do
4
+ subject { described_class.new(result, env, options) }
5
+
6
+ let(:result) { [ status, headers, body ] }
7
+ let(:env) { { 'HTTP_USER_AGENT' => user_agent } }
8
+ let(:options) { {} }
9
+
10
+ let(:user_agent) { 'Firefox' }
11
+ let(:status) { 200 }
12
+ let(:headers) { {} }
13
+ let(:body) { [] }
14
+
15
+ describe '#skip_processing?' do
16
+ it "should skip processing" do
17
+ subject.skip_processing?.should be_true
18
+ end
19
+ end
20
+
21
+ describe '#bad_browser?' do
22
+ let(:user_agent) { described_class::BAD_USER_AGENTS.first.source }
23
+
24
+ it { should be_bad_browser }
25
+ end
26
+
27
+ context 'ignored' do
28
+ let(:options) { { :ignore => [ %r{file} ] } }
29
+
30
+ context 'not root' do
31
+ let(:env) { { 'PATH_INFO' => '/this/file' } }
32
+
33
+ it { should be_ignored }
34
+ end
35
+
36
+ context 'root' do
37
+ let(:env) { { 'PATH_INFO' => '/' } }
38
+
39
+ it { should_not be_ignored }
40
+ end
41
+ end
42
+
43
+ context 'not text/html' do
44
+ let(:headers) { { 'Content-Type' => 'application/pdf' } }
45
+
46
+ it { should_not be_html }
47
+ end
48
+
49
+ context 'chunked response' do
50
+ let(:headers) { { 'Transfer-Encoding' => 'chunked' } }
51
+
52
+ it { should be_chunked }
53
+ end
54
+
55
+
56
+ context 'inline disposition' do
57
+ let(:headers) { { 'Content-Disposition' => 'inline; filename=my_inlined_file' } }
58
+
59
+ it { should be_inline }
60
+ end
61
+
62
+ describe '#ignored?' do
63
+ let(:path_info) { 'path info' }
64
+ let(:env) { { 'PATH_INFO' => path_info } }
65
+
66
+ context 'no ignore set' do
67
+ it { should_not be_ignored }
68
+ end
69
+
70
+ context 'ignore set' do
71
+ let(:options) { { :ignore => [ %r{#{path_info}} ] } }
72
+
73
+ it { should be_ignored }
74
+ end
75
+ end
76
+ end
77
+
@@ -12,253 +12,8 @@ describe Rack::LiveReload do
12
12
  let(:env) { {} }
13
13
  let(:options) { {} }
14
14
 
15
- describe "livereload local uri" do
16
- context 'does not exist' do
17
- before do
18
- stub_request(:any, 'localhost:35729/livereload.js').to_timeout
19
- end
20
-
21
- it { should use_vendored }
22
- end
23
-
24
- context 'exists' do
25
- before do
26
- stub_request(:any, 'localhost:35729/livereload.js')
27
- end
28
-
29
- it { should_not use_vendored }
30
- end
31
-
32
- context 'with custom port' do
33
- let(:options) { {:live_reload_port => '12348'}}
34
- context 'exists' do
35
- before do
36
- stub_request(:any, 'localhost:12348/livereload.js')
37
- end
38
- it { should_not use_vendored }
39
- end
40
- end
41
-
42
- context 'specify vendored' do
43
- let(:options) { { :source => :vendored } }
44
-
45
- it { should use_vendored }
46
- end
47
-
48
- context 'specify LR' do
49
- let(:options) { { :source => :livereload } }
50
-
51
- it { should_not use_vendored }
52
- end
53
- end
54
-
55
- context 'not text/html' do
56
- let(:ret) { [ 200, { 'Content-Type' => 'image/png' }, [ '<head></head>' ] ] }
57
-
58
- before do
59
- app.stubs(:call).with(env).returns(ret)
60
- end
61
-
62
- it 'should pass through' do
63
- middleware.call(env).should == ret
64
- end
65
- end
66
-
67
- context 'text/event-stram' do
68
- let(:body) { [ '<head></head>' ] }
69
- let(:ret) { [ 200, { 'Content-Type' => 'text/event-stream' }, body ] }
70
-
71
- before do
72
- app.stubs(:call).with(env).returns(ret)
73
- body.expects(:close).never
74
- body.stubs(:respond_to?).with(:close).returns(true)
75
- end
76
-
77
- it 'should pass through' do
78
- middleware.call(env).should == ret
79
- end
80
- end
81
-
82
- context 'chunked response' do
83
- let(:body) { [ '<head></head>' ] }
84
- let(:ret) { [ 200, { 'Transfer-Encoding' => 'chunked' }, body ] }
85
-
86
- before do
87
- app.stubs(:call).with(env).returns(ret)
88
- body.expects(:close).never
89
- body.stubs(:respond_to?).with(:close).returns(true)
90
- end
91
-
92
- it 'should pass through' do
93
- middleware.call(env).should == ret
94
- end
95
- end
96
-
97
- context 'inline disposition' do
98
- let(:body) { [ '<head></head>' ] }
99
- let(:ret) { [ 200, { 'Content-Disposition' => 'inline; filename=my_inlined_file' }, body ] }
100
-
101
- before do
102
- app.stubs(:call).with(env).returns(ret)
103
- body.expects(:close).never
104
- body.stubs(:respond_to?).with(:close).returns(true)
105
- end
106
-
107
- it 'should pass through' do
108
- middleware.call(env).should == ret
109
- end
110
- end
111
-
112
- context 'unknown Content-Type' do
113
- let(:ret) { [ 200, {}, [ 'hey ho' ] ] }
114
-
115
- before do
116
- app.stubs(:call).with(env).returns(ret)
117
- end
118
-
119
- it 'should not break' do
120
- middleware.call(env).should_not raise_error(NoMethodError, /You have a nil object/)
121
- end
122
- end
123
-
124
- context 'text/html' do
125
- before do
126
- app.stubs(:call).with(env).returns([ 200, { 'Content-Type' => 'text/html', 'Content-Length' => 0 }, [ page_html ] ])
127
- middleware.stubs(:use_vendored?).returns(true)
128
- end
129
-
130
- let(:host) { 'host' }
131
- let(:env) { { 'HTTP_HOST' => host } }
132
-
133
- let(:ret) { middleware._call(env) }
134
- let(:body) { ret.last.join }
135
- let(:length) { ret[1]['Content-Length'] }
136
-
137
- let(:page_html) { '<head></head>' }
138
-
139
- context 'vendored' do
140
- it 'should add the vendored livereload js script tag' do
141
- body.should include("script")
142
- body.should include(described_class::LIVERELOAD_JS_PATH)
143
-
144
- length.should == body.length.to_s
145
-
146
- described_class::LIVERELOAD_JS_PATH.should_not include(host)
147
-
148
- body.should include('swfobject')
149
- body.should include('web_socket')
150
- end
151
- end
152
-
153
- context 'at the top of the head tag' do
154
- let(:page_html) { '<head attribute="attribute"><script type="text/javascript" insert="first"></script><script type="text/javascript" insert="before"></script></head>' }
155
-
156
- let(:body_dom) { Nokogiri::XML(body) }
157
-
158
- it 'should add the livereload js script tag before all other script tags' do
159
- body_dom.at_css("head")[:attribute].should == 'attribute'
160
- body_dom.at_css("script:eq(5)")[:src].should include(described_class::LIVERELOAD_JS_PATH)
161
- body_dom.at_css("script:last-child")[:insert].should == "before"
162
- end
163
-
164
- end
165
-
166
- describe "LIVERELOAD_PORT value" do
167
- let(:options) { {:live_reload_port => 12345 }}
168
- it "sets the variable at the top of the file" do
169
- body.should include 'RACK_LIVERELOAD_PORT = 12345'
170
- end
171
- end
172
-
173
-
174
-
175
- context 'in header tags' do
176
- let(:page_html) { "<header class='hero'><h1>Just a normal header tag</h1></header>" }
177
-
178
- let(:body_dom) { Nokogiri::XML(body) }
179
-
180
- it 'should not add the livereload js' do
181
- body_dom.at_css("header")[:class].should == 'hero'
182
- body_dom.css('script').should be_empty
183
- end
184
- end
185
-
186
- context 'not vendored' do
187
- before do
188
- middleware.stubs(:use_vendored?).returns(false)
189
- end
190
-
191
- it 'should add the LR livereload js script tag' do
192
- body.should include("script")
193
- body.should include(middleware.livereload_local_uri.gsub('localhost', 'host'))
194
- end
195
- end
196
-
197
- context 'set options' do
198
- let(:middleware) { described_class.new(app, :host => new_host, :port => port, :min_delay => min_delay, :max_delay => max_delay) }
199
- let(:min_delay) { 5 }
200
- let(:max_delay) { 10 }
201
- let(:port) { 23 }
202
- let(:new_host) { 'myhost' }
203
-
204
- it 'should add the livereload.js script tag' do
205
- body.should include("mindelay=#{min_delay}")
206
- body.should include("maxdelay=#{max_delay}")
207
- body.should include("port=#{port}")
208
- body.should include("host=#{new_host}")
209
- end
210
- end
211
-
212
- context 'force flash' do
213
- let(:middleware) { described_class.new(app, :force_swf => true) }
214
-
215
- it 'should not add the flash shim' do
216
- body.should include('WEB_SOCKET_FORCE_FLASH')
217
- body.should include('swfobject')
218
- body.should include('web_socket')
219
- end
220
- end
221
-
222
- context 'no flash' do
223
- let(:middleware) { described_class.new(app, :no_swf => true) }
224
-
225
- it 'should not add the flash shim' do
226
- body.should_not include('swfobject')
227
- body.should_not include('web_socket')
228
- end
229
- end
230
-
231
- context 'no host at all' do
232
- let(:env) { {} }
233
-
234
- it 'should use localhost' do
235
- body.should include('localhost')
236
- end
237
- end
238
-
239
- context 'ignored' do
240
- let(:options) { { :ignore => [ %r{file} ] } }
241
-
242
- context 'not root' do
243
- let(:env) { { 'PATH_INFO' => '/this/file' } }
244
-
245
- it 'should have no change' do
246
- body.should_not include('script')
247
- end
248
- end
249
-
250
- context 'root' do
251
- let(:env) { { 'PATH_INFO' => '/' } }
252
-
253
- it 'should have script' do
254
- body.should include('script')
255
- end
256
- end
257
- end
258
- end
259
-
260
15
  context '/__rack/livereload.js' do
261
- let(:env) { { 'PATH_INFO' => described_class::LIVERELOAD_JS_PATH } }
16
+ let(:env) { { 'PATH_INFO' => described_class::BodyProcessor::LIVERELOAD_JS_PATH } }
262
17
 
263
18
  before do
264
19
  middleware.expects(:deliver_file).returns(true)
@@ -268,42 +23,5 @@ describe Rack::LiveReload do
268
23
  middleware._call(env).should be_true
269
24
  end
270
25
  end
271
-
272
- describe '#ignored?' do
273
- let(:path_info) { 'path info' }
274
-
275
- context 'no ignore set' do
276
- it { should_not be_ignored(path_info) }
277
- end
278
-
279
- context 'ignore set' do
280
- let(:options) { { :ignore => [ %r{#{path_info}} ] } }
281
-
282
- it { should be_ignored(path_info) }
283
- end
284
- end
285
-
286
- describe '#bad_browser?' do
287
- let(:user_agent) { described_class::BAD_USER_AGENTS.first.source }
288
-
289
- it { should be_bad_browser(user_agent) }
290
- end
291
-
292
- describe 'head tag regex' do
293
- let(:regex) { described_class::HEAD_TAG_REGEX }
294
- subject { regex }
295
-
296
- it { should be_kind_of(Regexp) }
297
-
298
- it 'only picks a valid <head> tag' do
299
- regex.match("<head></head>").to_s.should eq('<head>')
300
- regex.match("<head><title></title></head>").to_s.should eq('<head>')
301
- regex.match("<head attribute='something'><title></title></head>").to_s.should eq("<head attribute='something'>")
302
- end
303
-
304
- it 'responds false when no head tag' do
305
- regex.match("<header></header>").should be_false
306
- end
307
- end
308
26
  end
309
27
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-livereload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.13
4
+ version: 0.3.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-01 00:00:00.000000000 Z
12
+ date: 2013-05-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -301,8 +301,12 @@ files:
301
301
  - js/web_socket.js
302
302
  - lib/rack-livereload.rb
303
303
  - lib/rack/livereload.rb
304
+ - lib/rack/livereload/body_processor.rb
305
+ - lib/rack/livereload/processing_skip_analyzer.rb
304
306
  - rack-livereload.gemspec
305
307
  - skel/livereload.html.erb
308
+ - spec/rack/livereload/body_processor_spec.rb
309
+ - spec/rack/livereload/processing_skip_analyzer_spec.rb
306
310
  - spec/rack/livereload_spec.rb
307
311
  - spec/spec_helper.rb
308
312
  homepage: ''
@@ -319,7 +323,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
319
323
  version: '0'
320
324
  segments:
321
325
  - 0
322
- hash: 3462245992099149343
326
+ hash: -189623715678249777
323
327
  required_rubygems_version: !ruby/object:Gem::Requirement
324
328
  none: false
325
329
  requirements:
@@ -328,7 +332,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
328
332
  version: '0'
329
333
  segments:
330
334
  - 0
331
- hash: 3462245992099149343
335
+ hash: -189623715678249777
332
336
  requirements: []
333
337
  rubyforge_project: rack-livereload
334
338
  rubygems_version: 1.8.25
@@ -341,5 +345,7 @@ test_files:
341
345
  - features/step_definitions/then/i_should_not_have_livereload_code.rb
342
346
  - features/step_definitions/when/i_make_a_request_with_headers.rb
343
347
  - features/support/env.rb
348
+ - spec/rack/livereload/body_processor_spec.rb
349
+ - spec/rack/livereload/processing_skip_analyzer_spec.rb
344
350
  - spec/rack/livereload_spec.rb
345
351
  - spec/spec_helper.rb