hawkins 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,8 +6,7 @@ module Hawkins
6
6
  class << self
7
7
  COMMAND_OPTIONS = {
8
8
  "swf" => ["--swf", "Use Flash for WebSockets support"],
9
- # TODO Should probably only accept fnmatch-esque strings and convert them to regexs
10
- "ignore" => ["--ignore [REGEX]", "Files not to reload"],
9
+ "ignore" => ["--ignore GLOB1[,GLOB2[,...]]", "Files not to reload"],
11
10
  "min_delay" => ["--min-delay [SECONDS]", "Minimum reload delay"],
12
11
  "max_delay" => ["--max-delay [SECONDS]", "Maximum reload delay"],
13
12
  "reload_port" => ["--reload-port [PORT]", Integer, "Port for LiveReload to listen on"],
@@ -30,9 +29,7 @@ module Hawkins
30
29
  end
31
30
 
32
31
  cmd.action do |_, opts|
33
- # TODO need to figure out how to set defaults correctly
34
32
  opts["reload_port"] ||= LIVERELOAD_PORT
35
-
36
33
  opts["serving"] = true
37
34
  opts["watch"] = true unless opts.key?("watch")
38
35
  start(opts)
@@ -41,19 +38,22 @@ module Hawkins
41
38
  end
42
39
 
43
40
  def start(opts)
44
- opts = configuration_from_options(opts)
45
-
46
- @running = Queue.new
47
- @reload_reactor = LiveReloadReactor.new(opts)
48
- @reload_reactor.start
41
+ config = opts["config"]
42
+ @reload_reactor = nil
43
+ register_reload_hooks(opts)
49
44
  Jekyll::Commands::Build.process(opts)
45
+ opts["config"] = config
50
46
  LiveServe.process(opts)
51
47
  end
52
48
 
53
49
  def process(opts)
50
+ opts = configuration_from_options(opts)
54
51
  destination = opts["destination"]
55
52
  setup(destination)
56
53
 
54
+ @running = Queue.new
55
+ @reload_reactor.start(opts)
56
+
57
57
  @server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
58
58
 
59
59
  @server.mount("#{opts['baseurl']}/__livereload",
@@ -73,6 +73,38 @@ module Hawkins
73
73
  @server.shutdown if running?
74
74
  end
75
75
 
76
+ private
77
+ def register_reload_hooks(opts)
78
+ require_relative "websockets"
79
+ @reload_reactor = LiveReloadReactor.new
80
+
81
+ Jekyll::Hooks.register(:site, :post_render) do |site|
82
+ regenerator = Jekyll::Regenerator.new(site)
83
+ @changed_pages = site.pages.select do |p|
84
+ regenerator.regenerate?(p)
85
+ end
86
+ end
87
+
88
+ # A note on ignoring files: LiveReload errs on the side of reloading when it
89
+ # comes to the message it gets. If, for example, a page is ignored but a CSS
90
+ # file linked in the page isn't, the page will still be reloaded if the CSS
91
+ # file is contained in the message sent to LiveReload. Additionally, the
92
+ # path matching is very loose so that a message to reload "/" will always
93
+ # lead the page to reload since every page starts with "/".
94
+ Jekyll::Hooks.register(:site, :post_write) do
95
+ unless @changed_pages.nil? || !@reload_reactor.running?
96
+ ignore, @changed_pages = @changed_pages.partition do |p|
97
+ Array(opts["ignore"]).any? do |filter|
98
+ File.fnmatch(filter, Jekyll.sanitized_path(p.relative_path))
99
+ end
100
+ end
101
+ Jekyll.logger.debug "LiveReload:", "Ignoring #{ignore.map(&:relative_path)}"
102
+ @reload_reactor.reload(@changed_pages)
103
+ end
104
+ @changed_pages = nil
105
+ end
106
+ end
107
+
76
108
  # Do a base pre-setup of WEBRick so that everything is in place
77
109
  # when we get ready to party, checking for an setting up an error page
78
110
  # and making sure our destination exists.
@@ -63,6 +63,7 @@ module Hawkins
63
63
 
64
64
  content = <<-CONTENT
65
65
  ---
66
+ layout: post
66
67
  title: #{title}
67
68
  ---
68
69
  CONTENT
@@ -18,7 +18,7 @@ module Hawkins
18
18
  end
19
19
 
20
20
  def skip_processing?
21
- !html? || chunked? || inline? || ignored? || bad_browser?
21
+ !html? || chunked? || inline? || bad_browser?
22
22
  end
23
23
 
24
24
  def chunked?
@@ -29,11 +29,6 @@ module Hawkins
29
29
  @res['Content-Disposition'] =~ %r{^inline}
30
30
  end
31
31
 
32
- def ignored?
33
- path = @req.query_string.nil? ? @req.path_info : "#{@req.path_info}?#{@req.query_string}"
34
- @options["ignore"] && @options["ignore"].any? { |filter| path[filter] }
35
- end
36
-
37
32
  def bad_browser?
38
33
  BAD_USER_AGENTS.any? { |pattern| @req['User-Agent'] =~ pattern }
39
34
  end
@@ -63,12 +58,17 @@ module Hawkins
63
58
  end
64
59
 
65
60
  def process!
61
+ # @body will usually be a File object but Strings occur in rare cases
62
+ # that occur for reasons unknown to me.
66
63
  @new_body = []
67
- begin
68
- @body.each { |line| @new_body << line.to_s }
69
- ensure
70
- # @body will be a File object
71
- @body.close
64
+ if @body.respond_to?(:each)
65
+ begin
66
+ @body.each { |line| @new_body << line.to_s }
67
+ ensure
68
+ @body.close
69
+ end
70
+ else
71
+ @new_body = @body.lines
72
72
  end
73
73
 
74
74
  @content_length = 0
@@ -102,19 +102,12 @@ module Hawkins
102
102
  <script type="text/javascript" src="<%= @options["baseurl"] %>/__livereload/web_socket.js"></script>
103
103
  <% end %>
104
104
  <script type="text/javascript">
105
- HAWKINS_LIVERELOAD_PORT = <%= @options["reload_port"] %>;
106
- HAWKINS_LIVERELOAD_PROTOCOL = <%= livereload_protocol %>;
105
+ document.write('<script src="<%= livereload_source %>"></' + 'script>');
107
106
  </script>
108
- <script type="text/javascript" src="<%= livereload_source %>"></script>
109
107
  TEMPLATE
110
108
  ERB.new(Jekyll::Utils.strip_heredoc(template))
111
109
  end
112
110
 
113
- def livereload_protocol
114
- use_ssl = @options["ssl_cert"] && @options["ssl_key"]
115
- use_ssl ? '"wss://"' : '"ws://"'
116
- end
117
-
118
111
  def livereload_source
119
112
  use_ssl = @options["ssl_cert"] && @options["ssl_key"]
120
113
  protocol = use_ssl ? "https" : "http"
@@ -1,3 +1,3 @@
1
1
  module Hawkins
2
- VERSION = "2.0.2".freeze
2
+ VERSION = "2.0.3".freeze
3
3
  end
@@ -7,19 +7,27 @@ module Hawkins
7
7
  # despite the fact that the protocol itself uses WebSockets. This custom connection
8
8
  # class addresses the dual protocols that the server needs to understand.
9
9
  class HttpAwareConnection < EventMachine::WebSocket::Connection
10
- attr_reader :reload_file
10
+ attr_reader :reload_body, :reload_size
11
11
 
12
12
  def initialize(opts)
13
+ em_opts = {}
13
14
  @ssl_enabled = opts['ssl_cert'] && opts['ssl_key']
14
15
  if @ssl_enabled
15
- opts[:tls_options] = {
16
+ em_opts[:tls_options] = {
16
17
  :private_key_file => Jekyll.sanitized_path(opts['source'], opts['ssl_key']),
17
18
  :cert_chain_file => Jekyll.sanitized_path(opts['source'], opts['ssl_cert']),
18
19
  }
19
- opts[:secure] = true
20
+ em_opts[:secure] = true
20
21
  end
21
- super
22
- @reload_file = File.join(LIVERELOAD_DIR, "livereload.js")
22
+
23
+ # Too noisy even for debug level logging.
24
+ # em_opts[:debug] = true
25
+
26
+ super(em_opts)
27
+
28
+ reload_file = File.join(LIVERELOAD_DIR, "livereload.js")
29
+ @reload_body = File.read(reload_file)
30
+ @reload_size = File.size(reload_file)
23
31
  end
24
32
 
25
33
  def dispatch(data)
@@ -33,14 +41,13 @@ module Hawkins
33
41
  headers = [
34
42
  'HTTP/1.1 200 OK',
35
43
  'Content-Type: application/javascript',
36
- "Content-Length: #{File.size(reload_file)}",
44
+ "Content-Length: #{reload_size}",
37
45
  '',
38
46
  '',
39
47
  ].join("\r\n")
40
48
  send_data(headers)
41
- stream_file_data(reload_file).callback do
42
- close_connection_after_writing
43
- end
49
+ send_data(reload_body)
50
+ close_connection_after_writing
44
51
  else
45
52
  body = "This port only serves livereload.js over HTTP.\n"
46
53
  headers = [
@@ -61,23 +68,22 @@ module Hawkins
61
68
  attr_reader :thread
62
69
  attr_reader :opts
63
70
 
64
- def initialize(opts)
65
- @opts = opts
71
+ def initialize
66
72
  @thread = nil
67
73
  @websockets = []
68
74
  @connections_count = 0
69
75
  end
70
76
 
71
77
  def stop
78
+ EM.stop if EM.reactor_running?
72
79
  Jekyll.logger.debug("LiveReload Server:", "halted")
73
- @thread.kill unless @thread.nil?
74
80
  end
75
81
 
76
82
  def running?
77
83
  !@thread.nil? && @thread.alive?
78
84
  end
79
85
 
80
- def start
86
+ def start(opts)
81
87
  @thread = Thread.new do
82
88
  # Use epoll if the kernel supports it
83
89
  EM.epoll
@@ -99,22 +105,8 @@ module Hawkins
99
105
  end
100
106
  end
101
107
  end
102
-
103
- Jekyll::Hooks.register(:site, :post_render) do |site|
104
- regenerator = Jekyll::Regenerator.new(site)
105
- @changed_pages = site.pages.select do |p|
106
- regenerator.regenerate?(p)
107
- end
108
- end
109
-
110
- Jekyll::Hooks.register(:site, :post_write) do
111
- reload(@changed_pages) unless @changed_pages.nil?
112
- @changed_pages = nil
113
- end
114
108
  end
115
109
 
116
- private
117
-
118
110
  # For a description of the protocol see http://feedback.livereload.com/knowledgebase/articles/86174-livereload-protocol
119
111
  def reload(pages)
120
112
  pages.each do |p|
@@ -117,7 +117,8 @@ module Hawkins
117
117
  client.ssl_config.add_trust_ca(cert)
118
118
  content = client.get_content(
119
119
  "https://#{opts['host']}:#{opts['port']}/#{opts['baseurl']}/hello.html")
120
- expect(content).to include('HAWKINS_LIVERELOAD_PROTOCOL = "wss://";')
120
+ expect(content).to include(
121
+ "src=\"https://#{opts['host']}:#{opts['reload_port']}/livereload.js")
121
122
  end
122
123
 
123
124
  it "serves nothing else over HTTP on the default LiveReload port" do
@@ -131,9 +132,7 @@ module Hawkins
131
132
  opts = serve(standard_opts)
132
133
  content = client.get_content(
133
134
  "http://#{opts['host']}:#{opts['port']}/#{opts['baseurl']}/hello.html")
134
- expect(content).to include("HAWKINS_LIVERELOAD_PORT = #{opts['reload_port']}")
135
- expect(content).to include('HAWKINS_LIVERELOAD_PROTOCOL = "ws://";')
136
- expect(content).to include("livereload.js?snipver=1")
135
+ expect(content).to include("livereload.js?snipver=1&amp;port=#{opts['livereload_port']}")
137
136
  expect(content).to include("I am a simple web page")
138
137
  end
139
138
 
@@ -37,6 +37,7 @@ module Hawkins
37
37
  title = "1999"
38
38
  expected_body = <<-BODY.gsub(/^\s*/, '')
39
39
  ---
40
+ layout: post
40
41
  title: #{title}
41
42
  ---
42
43
  BODY
@@ -60,6 +61,7 @@ module Hawkins
60
61
  title = "Raspberry Beret"
61
62
  expected_body = <<-BODY.gsub(/^\s*/, '')
62
63
  ---
64
+ layout: post
63
65
  title: #{title}
64
66
  ---
65
67
  BODY
@@ -152,7 +154,7 @@ module Hawkins
152
154
 
153
155
  %w(xemacs emacs).each do |editor|
154
156
  allow(Commands::Post).to receive(:exec)
155
- .with(editor, '+3', /#{expected_file}/)
157
+ .with(editor, '+4', /#{expected_file}/)
156
158
  .and_return(nil)
157
159
  stub_const("ENV", ENV.to_h.tap { |h| h['VISUAL'] = editor })
158
160
  expect do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hawkins
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Wood
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-10 00:00:00.000000000 Z
11
+ date: 2016-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll
@@ -202,6 +202,7 @@ files:
202
202
  - ".document"
203
203
  - ".gitignore"
204
204
  - ".rubocop.yml"
205
+ - ".travis.yml"
205
206
  - Gemfile
206
207
  - LICENSE.txt
207
208
  - README.md