class Jekyll::Commands::Serve::LiveReloadReactor

Attributes

started_event[R]
stopped_event[R]
thread[R]

Public Class Methods

new() click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 13
def initialize
  @websockets = []
  @connections_count = 0
  @started_event = Utils::ThreadEvent.new
  @stopped_event = Utils::ThreadEvent.new
end

Public Instance Methods

handle_websockets_event(websocket) click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 31
def handle_websockets_event(websocket)
  websocket.onopen { |handshake| connect(websocket, handshake) }
  websocket.onclose { disconnect(websocket) }
  websocket.onmessage { |msg| print_message(msg) }
  websocket.onerror { |error| log_error(error) }
end
reload(pages) click to toggle source

For a description of the protocol see feedback.livereload.com/knowledgebase/articles/86174-livereload-protocol

# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 67
def reload(pages)
  pages.each do |p|
    json_message = JSON.dump(
      :command => "reload",
      :path    => p.url,
      :liveCSS => true
    )

    Jekyll.logger.debug "LiveReload:", "Reloading URL #{p.url.inspect}"
    @websockets.each { |ws| ws.send(json_message) }
  end
end
running?() click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 27
def running?
  EM.reactor_running?
end
start(opts) click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 38
def start(opts)
  @thread = Thread.new do
    # Use epoll if the kernel supports it
    EM.epoll
    EM.run do
      EM.error_handler { |e| log_error(e) }

      EM.start_server(
        opts["host"],
        opts["livereload_port"],
        HttpAwareConnection,
        opts
      ) do |ws|
        handle_websockets_event(ws)
      end

      # Notify blocked threads that EventMachine has started or shutdown
      EM.schedule { @started_event.set }
      EM.add_shutdown_hook { @stopped_event.set }

      Jekyll.logger.info "LiveReload address:",
                         "http://#{opts["host"]}:#{opts["livereload_port"]}"
    end
  end
  @thread.abort_on_exception = true
end
stop() click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 20
def stop
  # There is only one EventMachine instance per Ruby process so stopping
  # it here will stop the reactor thread we have running.
  EM.stop if EM.reactor_running?
  Jekyll.logger.debug "LiveReload Server:", "halted"
end

Private Instance Methods

connect(websocket, handshake) click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 82
def connect(websocket, handshake)
  @connections_count += 1
  if @connections_count == 1
    message = "Browser connected"
    message += " over SSL/TLS" if handshake.secure?
    Jekyll.logger.info "LiveReload:", message
  end
  websocket.send(
    JSON.dump(
      :command    => "hello",
      :protocols  => ["http://livereload.com/protocols/official-7"],
      :serverName => "jekyll"
    )
  )

  @websockets << websocket
end
disconnect(websocket) click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 100
def disconnect(websocket)
  @websockets.delete(websocket)
end
log_error(error) click to toggle source
# File lib/jekyll/commands/serve/live_reload_reactor.rb, line 111
def log_error(error)
  Jekyll.logger.error "LiveReload experienced an error. " \
                      "Run with --trace for more information."
  raise error
end
print_message(json_message) click to toggle source