hawkins 2.0.2 → 2.0.3

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.
@@ -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