lib/jekyll/commands/serve/live_reload_reactor.rb in jekyll-4.2.0 vs lib/jekyll/commands/serve/live_reload_reactor.rb in jekyll-4.2.1

- old
+ new

@@ -1,122 +1,122 @@ -# frozen_string_literal: true - -require "em-websocket" - -require_relative "websockets" - -module Jekyll - module Commands - class Serve - class LiveReloadReactor - attr_reader :started_event - attr_reader :stopped_event - attr_reader :thread - - def initialize - @websockets = [] - @connections_count = 0 - @started_event = Utils::ThreadEvent.new - @stopped_event = Utils::ThreadEvent.new - end - - 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 - - def running? - EM.reactor_running? - end - - 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 - - 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 - - # For a description of the protocol see - # http://feedback.livereload.com/knowledgebase/articles/86174-livereload-protocol - def reload(pages) - pages.each do |p| - json_message = JSON.dump( - :command => "reload", - :path => p.url, - :liveCSS => true - ) - - Jekyll.logger.debug "LiveReload:", "Reloading #{p.url}" - Jekyll.logger.debug "", json_message - @websockets.each { |ws| ws.send(json_message) } - end - end - - private - - 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 - - def disconnect(websocket) - @websockets.delete(websocket) - end - - def print_message(json_message) - msg = JSON.parse(json_message) - # Not sure what the 'url' command even does in LiveReload. The spec is silent - # on its purpose. - Jekyll.logger.info "LiveReload:", "Browser URL: #{msg["url"]}" if msg["command"] == "url" - end - - def log_error(error) - Jekyll.logger.error "LiveReload experienced an error. " \ - "Run with --trace for more information." - raise error - end - end - end - end -end +# frozen_string_literal: true + +require "em-websocket" + +require_relative "websockets" + +module Jekyll + module Commands + class Serve + class LiveReloadReactor + attr_reader :started_event + attr_reader :stopped_event + attr_reader :thread + + def initialize + @websockets = [] + @connections_count = 0 + @started_event = Utils::ThreadEvent.new + @stopped_event = Utils::ThreadEvent.new + end + + 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 + + def running? + EM.reactor_running? + end + + 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 + + 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 + + # For a description of the protocol see + # http://feedback.livereload.com/knowledgebase/articles/86174-livereload-protocol + def reload(pages) + pages.each do |p| + json_message = JSON.dump( + :command => "reload", + :path => p.url, + :liveCSS => true + ) + + Jekyll.logger.debug "LiveReload:", "Reloading #{p.url}" + Jekyll.logger.debug "", json_message + @websockets.each { |ws| ws.send(json_message) } + end + end + + private + + 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 + + def disconnect(websocket) + @websockets.delete(websocket) + end + + def print_message(json_message) + msg = JSON.parse(json_message) + # Not sure what the 'url' command even does in LiveReload. The spec is silent + # on its purpose. + Jekyll.logger.info "LiveReload:", "Browser URL: #{msg["url"]}" if msg["command"] == "url" + end + + def log_error(error) + Jekyll.logger.error "LiveReload experienced an error. " \ + "Run with --trace for more information." + raise error + end + end + end + end +end