class Hawkins::Commands::LiveServe
Constants
- COMMAND_OPTIONS
- LIVERELOAD_PORT
Attributes
is_running[R]
mutex[R]
running_cond[R]
Public Class Methods
init_with_program(prog)
click to toggle source
# File lib/hawkins/liveserve.rb, line 27 def init_with_program(prog) prog.command(:liveserve) do |cmd| cmd.description "Serve your site locally with LiveReload" cmd.syntax "liveserve [options]" cmd.alias :liveserver cmd.alias :l add_build_options(cmd) COMMAND_OPTIONS.each do |key, val| cmd.option(key, *val) end cmd.action do |_, opts| opts["reload_port"] ||= LIVERELOAD_PORT opts["serving"] = true opts["watch"] = true unless opts.key?("watch") start(opts) end end end
process(opts)
click to toggle source
# File lib/hawkins/liveserve.rb, line 57 def process(opts) opts = configuration_from_options(opts) destination = opts["destination"] setup(destination) @reload_reactor.start(opts) @server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") } @server.mount("#{opts['baseurl']}/__livereload", WEBrick::HTTPServlet::FileHandler, LIVERELOAD_DIR) @server.mount(opts["baseurl"], ReloadServlet, destination, file_handler_opts) Jekyll.logger.info "Server address:", server_address(@server, opts) launch_browser(@server, opts) if opts["open_url"] boot_or_detach(@server, opts) end
shutdown()
click to toggle source
# File lib/hawkins/liveserve.rb, line 74 def shutdown @server.shutdown if @is_running end
start(opts)
click to toggle source
# File lib/hawkins/liveserve.rb, line 48 def start(opts) config = opts["config"] @reload_reactor = nil register_reload_hooks(opts) Jekyll::Commands::Build.process(opts) opts["config"] = config LiveServe.process(opts) end
Private Class Methods
boot_or_detach(server, opts)
click to toggle source
Keep in our area with a thread or detach the server as requested by the user. This method determines what we do based on what you ask us to do.
# File lib/hawkins/liveserve.rb, line 205 def boot_or_detach(server, opts) if opts["detach"] pid = Process.fork do server.start end Process.detach(pid) Jekyll.logger.info "Server detached with pid '#{pid}'.", \ "Run `pkill -f jekyll' or `kill -9 #{pid}' to stop the server." else t = Thread.new { server.start } trap("INT") { server.shutdown } t.join end end
create_error_page()
click to toggle source
# File lib/hawkins/liveserve.rb, line 121 def create_error_page @header["Content-Type"] = "text/html; charset=UTF-8" @body = IO.read(File.join(@config[:DocumentRoot], "404.html")) end
enable_logging(opts)
click to toggle source
Make the stack verbose if the user requests it.
# File lib/hawkins/liveserve.rb, line 224 def enable_logging(opts) opts[:AccessLog] = [] level = WEBrick::Log.const_get(opts[:JekyllOptions]["verbose"] ? :DEBUG : :WARN) opts[:Logger] = WEBrick::Log.new($stdout, level) end
enable_ssl(opts)
click to toggle source
Add SSL to the stack if the user triggers –enable-ssl and they provide both types of certificates commonly needed. Raise if they forget to add one of the certificates.
# File lib/hawkins/liveserve.rb, line 235 def enable_ssl(opts) jekyll_opts = opts[:JekyllOptions] return if !jekyll_opts['ssl_cert'] && !jekyll_opts['ssl_key'] if !jekyll_opts['ssl_cert'] || !jekyll_opts['ssl_key'] raise "--ssl-cert or --ssl-key missing." end Jekyll.logger.info("LiveReload:", "Serving over SSL/TLS. If you are using a "\ "certificate signed by an unknown CA, you will need to add an exception for both "\ "#{jekyll_opts['host']}:#{jekyll_opts['port']} and "\ "#{jekyll_opts['host']}:#{jekyll_opts['reload_port']}") require "openssl" require "webrick/https" source_key = Jekyll.sanitized_path(jekyll_opts['source'], jekyll_opts['ssl_key']) source_certificate = Jekyll.sanitized_path(jekyll_opts['source'], jekyll_opts['ssl_cert']) opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read(source_certificate)) opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read(source_key)) opts[:SSLEnable] = true end
file_handler_opts()
click to toggle source
Recreate NondisclosureName under utf-8 circumstance
# File lib/hawkins/liveserve.rb, line 159 def file_handler_opts WEBrick::Config::FileHandler.merge( :FancyIndexing => true, :NondisclosureName => [ '.ht*', '~*' ] ) end
launch_browser(server, opts)
click to toggle source
# File lib/hawkins/liveserve.rb, line 188 def launch_browser(server, opts) command = if Jekyll::Utils::Platforms.windows? "start" elsif Jekyll::Utils::Platforms.osx? "open" else "xdg-open" end system command, server_address(server, opts) end
mime_types()
click to toggle source
# File lib/hawkins/liveserve.rb, line 297 def mime_types file = File.expand_path('../mime.types', File.dirname(__FILE__)) WEBrick::HTTPUtils.load_mime_types(file) end
register_reload_hooks(opts)
click to toggle source
# File lib/hawkins/liveserve.rb, line 79 def register_reload_hooks(opts) require_relative "websockets" @reload_reactor = LiveReloadReactor.new Jekyll::Hooks.register(:site, :post_render) do |site| regenerator = Jekyll::Regenerator.new(site) @changed_pages = site.pages.select do |p| regenerator.regenerate?(p) end end # A note on ignoring files: LiveReload errs on the side of reloading when it # comes to the message it gets. If, for example, a page is ignored but a CSS # file linked in the page isn't, the page will still be reloaded if the CSS # file is contained in the message sent to LiveReload. Additionally, the # path matching is very loose so that a message to reload "/" will always # lead the page to reload since every page starts with "/". Jekyll::Hooks.register(:site, :post_write) do if @changed_pages && @reload_reactor && @reload_reactor.running? ignore, @changed_pages = @changed_pages.partition do |p| Array(opts["ignore"]).any? do |filter| File.fnmatch(filter, Jekyll.sanitized_path(p.relative_path)) end end Jekyll.logger.debug "LiveReload:", "Ignoring #{ignore.map(&:relative_path)}" @reload_reactor.reload(@changed_pages) end @changed_pages = nil end end
server_address(server, opts)
click to toggle source
# File lib/hawkins/liveserve.rb, line 171 def server_address(server, opts) address = server.config[:BindAddress] baseurl = "#{opts['baseurl']}/" if opts["baseurl"] port = server.config[:Port] if opts['ssl_cert'] && opts['ssl_key'] protocol = "https" else protocol = "http" end "#{protocol}://#{address}:#{port}#{baseurl}" end
setup(destination)
click to toggle source
Do a base pre-setup of WEBRick so that everything is in place when we get ready to party, checking for an setting up an error page and making sure our destination exists.
# File lib/hawkins/liveserve.rb, line 115 def setup(destination) require_relative "./servlet" FileUtils.mkdir_p(destination) if File.exist?(File.join(destination, "404.html")) WEBrick::HTTPResponse.class_eval do def create_error_page @header["Content-Type"] = "text/html; charset=UTF-8" @body = IO.read(File.join(@config[:DocumentRoot], "404.html")) end end end end
start_callback(detached)
click to toggle source
# File lib/hawkins/liveserve.rb, line 257 def start_callback(detached) unless detached proc do mutex.synchronize do unless @reload_reactor.nil? @reload_reactor.reactor_mutex.synchronize do unless EM.reactor_running? @reload_reactor.reactor_running_cond.wait(@reload_reactor.reactor_mutex) end end end @is_running = true Jekyll.logger.info("Server running...", "press ctrl-c to stop.") running_cond.signal end end end end
stop_callback(detached)
click to toggle source
# File lib/hawkins/liveserve.rb, line 277 def stop_callback(detached) unless detached proc do mutex.synchronize do unless @reload_reactor.nil? @reload_reactor.stop @reload_reactor.reactor_mutex.synchronize do if EM.reactor_running? @reload_reactor.reactor_running_cond.wait(@reload_reactor.reactor_mutex) end end end @is_running = false running_cond.signal end end end end
webrick_opts(opts)
click to toggle source
# File lib/hawkins/liveserve.rb, line 132 def webrick_opts(opts) opts = { :JekyllOptions => opts, :DoNotReverseLookup => true, :MimeTypes => mime_types, :DocumentRoot => opts["destination"], :StartCallback => start_callback(opts["detach"]), :StopCallback => stop_callback(opts["detach"]), :BindAddress => opts["host"], :Port => opts["port"], :DirectoryIndex => %w( index.htm index.html index.rhtml index.cgi index.xml ), } enable_ssl(opts) enable_logging(opts) opts end