rack-livereload 0.3.13 → 0.3.14

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/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