Initialize each command in its own class so we can be *magical*.
This commit is contained in:
parent
7288176f65
commit
e746b3bd5f
92
bin/jekyll
92
bin/jekyll
|
@ -8,17 +8,6 @@ require 'mercenary'
|
||||||
|
|
||||||
Jekyll::Deprecator.process(ARGV)
|
Jekyll::Deprecator.process(ARGV)
|
||||||
|
|
||||||
def add_build_options(c)
|
|
||||||
c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
|
||||||
c.option 'future', '--future', 'Publishes posts with a future date'
|
|
||||||
c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
|
|
||||||
c.option 'watch', '-w', '--watch', 'Watch for changes and rebuild'
|
|
||||||
c.option 'lsi', '--lsi', 'Use LSI for improved related posts'
|
|
||||||
c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder'
|
|
||||||
c.option 'quiet', '-q', '--quiet', 'Silence output.'
|
|
||||||
c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
|
|
||||||
end
|
|
||||||
|
|
||||||
Mercenary.program(:jekyll) do |p|
|
Mercenary.program(:jekyll) do |p|
|
||||||
p.version Jekyll::VERSION
|
p.version Jekyll::VERSION
|
||||||
p.description 'Jekyll is a blog-aware, static site generator in Ruby'
|
p.description 'Jekyll is a blog-aware, static site generator in Ruby'
|
||||||
|
@ -30,9 +19,11 @@ Mercenary.program(:jekyll) do |p|
|
||||||
p.option 'plugins', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
p.option 'plugins', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
||||||
p.option 'layouts', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
|
p.option 'layouts', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
|
||||||
|
|
||||||
|
Jekyll::Command.subclasses.each { |c| c.init_with_program(p) }
|
||||||
|
|
||||||
p.action do |args, options|
|
p.action do |args, options|
|
||||||
if args.empty?
|
if args.empty?
|
||||||
p.go(["-h"])
|
puts p
|
||||||
else
|
else
|
||||||
unless p.has_command?(args.first)
|
unless p.has_command?(args.first)
|
||||||
Jekyll.logger.abort_with "Invalid command. Use --help for more information"
|
Jekyll.logger.abort_with "Invalid command. Use --help for more information"
|
||||||
|
@ -40,83 +31,8 @@ Mercenary.program(:jekyll) do |p|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
p.command(:new) do |c|
|
|
||||||
c.syntax 'jekyll new PATH'
|
|
||||||
c.description 'Creates a new Jekyll site scaffold in PATH'
|
|
||||||
|
|
||||||
c.option 'force', '--force', 'Force creation even if PATH already exists'
|
|
||||||
c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
|
|
||||||
|
|
||||||
c.action do |args, options|
|
|
||||||
Jekyll::Commands::New.process(args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
p.command(:build) do |c|
|
|
||||||
c.syntax 'jekyll build [options]'
|
|
||||||
c.description 'Build your site'
|
|
||||||
|
|
||||||
add_build_options(c)
|
|
||||||
|
|
||||||
c.action do |args, options|
|
|
||||||
options["serving"] = false
|
|
||||||
config = Jekyll.configuration(options)
|
|
||||||
Jekyll::Commands::Build.process(config)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
p.command(:serve) do |c|
|
|
||||||
c.syntax 'jekyll serve [options]'
|
|
||||||
c.description 'Serve your site locally'
|
|
||||||
c.alias :server
|
|
||||||
|
|
||||||
add_build_options(c)
|
|
||||||
|
|
||||||
c.option 'detach', '-B', '--detach', 'Run the server in the background (detach)'
|
|
||||||
c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
|
|
||||||
c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
|
|
||||||
c.option 'baseurl', '-b', '--baseurl [URL]', 'Base URL'
|
|
||||||
|
|
||||||
c.action do |args, options|
|
|
||||||
options["serving"] ||= true
|
|
||||||
options = Jekyll.configuration(options)
|
|
||||||
Jekyll::Commands::Build.process(options)
|
|
||||||
Jekyll::Commands::Serve.process(options)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
p.command(:doctor) do |c|
|
|
||||||
c.syntax 'jekyll doctor'
|
|
||||||
c.description 'Search site and print specific deprecation warnings'
|
|
||||||
c.alias(:hyde)
|
|
||||||
|
|
||||||
c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
|
||||||
|
|
||||||
c.action do |args, options|
|
|
||||||
options = Jekyll.configuration(options)
|
|
||||||
Jekyll::Commands::Doctor.process(options)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
p.command(:docs) do |c|
|
|
||||||
c.syntax 'jekyll docs'
|
|
||||||
c.description "Launch local server with docs for Jekyll v#{Jekyll::VERSION}"
|
|
||||||
|
|
||||||
c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
|
|
||||||
c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
|
|
||||||
|
|
||||||
c.action do |args, options|
|
|
||||||
options = Jekyll.configuration(options.merge!({
|
|
||||||
'source' => File.expand_path("../site", File.dirname(__FILE__)),
|
|
||||||
'destination' => File.expand_path("../site/_site", File.dirname(__FILE__))
|
|
||||||
}))
|
|
||||||
Jekyll::Commands::Build.process(options)
|
|
||||||
Jekyll::Commands::Serve.process(options)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
p.command(:import) do |c|
|
p.command(:import) do |c|
|
||||||
c.syntax 'jekyll import <platform> [options]'
|
c.syntax 'import <platform> [options]'
|
||||||
c.description 'Import your old blog to Jekyll'
|
c.description 'Import your old blog to Jekyll'
|
||||||
importers = []
|
importers = []
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,79 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
class Command
|
class Command
|
||||||
def self.globs(source, destination)
|
|
||||||
Dir.chdir(source) do
|
class << self
|
||||||
dirs = Dir['*'].select { |x| File.directory?(x) }
|
|
||||||
dirs -= [destination, File.expand_path(destination), File.basename(destination)]
|
# A list of subclasses of Jekyll::Command
|
||||||
dirs = dirs.map { |x| "#{x}/**/*" }
|
def subclasses
|
||||||
dirs += ['*']
|
@subclasses ||= []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Keep a list of subclasses of Jekyll::Command every time it's inherited
|
||||||
|
# Called automatically.
|
||||||
|
#
|
||||||
|
# base - the subclass
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
|
def inherited(base)
|
||||||
|
subclasses << base
|
||||||
|
super(base)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Listing of all directories (globbed to include subfiles and folders)
|
||||||
|
#
|
||||||
|
# source - the source path
|
||||||
|
# destination - the destination path
|
||||||
|
#
|
||||||
|
# Returns an Array of directory globs in the source, excluding the destination
|
||||||
|
def globs(source, destination)
|
||||||
|
Dir.chdir(source) do
|
||||||
|
dirs = Dir['*'].select { |x| File.directory?(x) }
|
||||||
|
dirs -= [destination, File.expand_path(destination), File.basename(destination)]
|
||||||
|
dirs = dirs.map { |x| "#{x}/**/*" }
|
||||||
|
dirs += ['*']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run Site#process and catch errors
|
||||||
|
#
|
||||||
|
# site - the Jekyll::Site object
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
|
def process_site(site)
|
||||||
|
site.process
|
||||||
|
rescue Jekyll::FatalException => e
|
||||||
|
Jekyll.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
|
||||||
|
Jekyll.logger.error "", "------------------------------------"
|
||||||
|
Jekyll.logger.error "", e.message
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Create a full Jekyll configuration with the options passed in as overrides
|
||||||
|
#
|
||||||
|
# options - the configuration overrides
|
||||||
|
#
|
||||||
|
# Returns a full Jekyll configuration
|
||||||
|
def configuration_from_options(options)
|
||||||
|
Jekyll.configuration(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Add common options to a command for building configuration
|
||||||
|
#
|
||||||
|
# c - the Jekyll::Command to add these options to
|
||||||
|
#
|
||||||
|
# Returns nothing
|
||||||
|
def add_build_options(c)
|
||||||
|
c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
||||||
|
c.option 'future', '--future', 'Publishes posts with a future date'
|
||||||
|
c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
|
||||||
|
c.option 'watch', '-w', '--watch', 'Watch for changes and rebuild'
|
||||||
|
c.option 'lsi', '--lsi', 'Use LSI for improved related posts'
|
||||||
|
c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder'
|
||||||
|
c.option 'quiet', '-q', '--quiet', 'Silence output.'
|
||||||
|
c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Static: Run Site#process and catch errors
|
|
||||||
#
|
|
||||||
# site - the Jekyll::Site object
|
|
||||||
#
|
|
||||||
# Returns nothing
|
|
||||||
def self.process_site(site)
|
|
||||||
site.process
|
|
||||||
rescue Jekyll::FatalException => e
|
|
||||||
puts
|
|
||||||
Jekyll.logger.error "ERROR:", "YOUR SITE COULD NOT BE BUILT:"
|
|
||||||
Jekyll.logger.error "", "------------------------------------"
|
|
||||||
Jekyll.logger.error "", e.message
|
|
||||||
exit(1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,72 +1,96 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module Commands
|
module Commands
|
||||||
class Build < Command
|
class Build < Command
|
||||||
def self.process(options)
|
|
||||||
site = Jekyll::Site.new(options)
|
|
||||||
|
|
||||||
Jekyll.logger.log_level = Jekyll::Stevenson::ERROR if options['quiet']
|
class << self
|
||||||
|
|
||||||
build(site, options)
|
# Create the Mercenary command for the Jekyll CLI for this Command
|
||||||
watch(site, options) if options['watch']
|
def init_with_program(prog)
|
||||||
end
|
prog.command(:build) do |c|
|
||||||
|
c.syntax 'build [options]'
|
||||||
|
c.description 'Build your site'
|
||||||
|
|
||||||
# Private: Build the site from source into destination.
|
add_build_options(c)
|
||||||
#
|
|
||||||
# site - A Jekyll::Site instance
|
|
||||||
# options - A Hash of options passed to the command
|
|
||||||
#
|
|
||||||
# Returns nothing.
|
|
||||||
def self.build(site, options)
|
|
||||||
source = options['source']
|
|
||||||
destination = options['destination']
|
|
||||||
Jekyll.logger.info "Source:", source
|
|
||||||
Jekyll.logger.info "Destination:", destination
|
|
||||||
print Jekyll.logger.formatted_topic "Generating..."
|
|
||||||
process_site(site)
|
|
||||||
puts "done."
|
|
||||||
end
|
|
||||||
|
|
||||||
# Private: Watch for file changes and rebuild the site.
|
c.action do |args, options|
|
||||||
#
|
options["serving"] = false
|
||||||
# site - A Jekyll::Site instance
|
Jekyll::Commands::Build.process(options)
|
||||||
# options - A Hash of options passed to the command
|
end
|
||||||
#
|
end
|
||||||
# Returns nothing.
|
|
||||||
def self.watch(site, options)
|
|
||||||
require 'listen'
|
|
||||||
|
|
||||||
source = options['source']
|
|
||||||
destination = options['destination']
|
|
||||||
|
|
||||||
begin
|
|
||||||
dest = Pathname.new(destination).relative_path_from(Pathname.new(source)).to_s
|
|
||||||
ignored = Regexp.new(Regexp.escape(dest))
|
|
||||||
rescue ArgumentError
|
|
||||||
# Destination is outside the source, no need to ignore it.
|
|
||||||
ignored = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Jekyll.logger.info "Auto-regeneration:", "enabled"
|
# Build your jekyll site
|
||||||
|
# Continuously watch if `watch` is set to true in the config.
|
||||||
|
def process(options)
|
||||||
|
options = configuration_from_options(options)
|
||||||
|
site = Jekyll::Site.new(options)
|
||||||
|
|
||||||
listener = Listen.to(source, :ignore => ignored) do |modified, added, removed|
|
Jekyll.logger.log_level = Jekyll::Stevenson::ERROR if options['quiet']
|
||||||
t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
n = modified.length + added.length + removed.length
|
build(site, options)
|
||||||
print Jekyll.logger.formatted_topic("Regenerating:") + "#{n} files at #{t} "
|
watch(site, options) if options['watch']
|
||||||
|
end
|
||||||
|
|
||||||
|
# Build your Jekyll site.
|
||||||
|
#
|
||||||
|
# site - the Jekyll::Site instance to build
|
||||||
|
# options - the
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def build(site, options)
|
||||||
|
source = options['source']
|
||||||
|
destination = options['destination']
|
||||||
|
Jekyll.logger.info "Source:", source
|
||||||
|
Jekyll.logger.info "Destination:", destination
|
||||||
|
Jekyll.logger.info "Generating..."
|
||||||
process_site(site)
|
process_site(site)
|
||||||
puts "...done."
|
Jekyll.logger.info "", "done."
|
||||||
end
|
end
|
||||||
listener.start
|
|
||||||
|
|
||||||
unless options['serving']
|
# Private: Watch for file changes and rebuild the site.
|
||||||
trap("INT") do
|
#
|
||||||
listener.stop
|
# site - A Jekyll::Site instance
|
||||||
puts " Halting auto-regeneration."
|
# options - A Hash of options passed to the command
|
||||||
exit 0
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def watch(site, options)
|
||||||
|
require 'listen'
|
||||||
|
|
||||||
|
source = options['source']
|
||||||
|
destination = options['destination']
|
||||||
|
|
||||||
|
begin
|
||||||
|
dest = Pathname.new(destination).relative_path_from(Pathname.new(source)).to_s
|
||||||
|
ignored = Regexp.new(Regexp.escape(dest))
|
||||||
|
rescue ArgumentError
|
||||||
|
# Destination is outside the source, no need to ignore it.
|
||||||
|
ignored = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
loop { sleep 1000 }
|
Jekyll.logger.info "Auto-regeneration:", "enabled"
|
||||||
|
|
||||||
|
listener = Listen.to(source, :ignore => ignored) do |modified, added, removed|
|
||||||
|
t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
n = modified.length + added.length + removed.length
|
||||||
|
print Jekyll.logger.formatted_topic("Regenerating:") + "#{n} files at #{t} "
|
||||||
|
process_site(site)
|
||||||
|
puts "...done."
|
||||||
|
end
|
||||||
|
listener.start
|
||||||
|
|
||||||
|
unless options['serving']
|
||||||
|
trap("INT") do
|
||||||
|
listener.stop
|
||||||
|
puts " Halting auto-regeneration."
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
loop { sleep 1000 }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
end # end of class << self
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
module Jekyll
|
||||||
|
module Commands
|
||||||
|
class Docs < Command
|
||||||
|
|
||||||
|
class << self
|
||||||
|
|
||||||
|
def init_with_program(prog)
|
||||||
|
prog.command(:docs) do |c|
|
||||||
|
c.syntax 'docs'
|
||||||
|
c.description "Launch local server with docs for Jekyll v#{Jekyll::VERSION}"
|
||||||
|
|
||||||
|
c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
|
||||||
|
c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
|
||||||
|
|
||||||
|
c.action do |args, options|
|
||||||
|
options.merge!({
|
||||||
|
'source' => File.expand_path("../../../site", File.dirname(__FILE__)),
|
||||||
|
'destination' => File.expand_path("../../../site/_site", File.dirname(__FILE__))
|
||||||
|
})
|
||||||
|
Jekyll::Commands::Build.process(options)
|
||||||
|
Jekyll::Commands::Serve.process(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,8 +2,23 @@ module Jekyll
|
||||||
module Commands
|
module Commands
|
||||||
class Doctor < Command
|
class Doctor < Command
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
|
def init_with_program(prog)
|
||||||
|
prog.command(:doctor) do |c|
|
||||||
|
c.syntax 'doctor'
|
||||||
|
c.description 'Search site and print specific deprecation warnings'
|
||||||
|
c.alias(:hyde)
|
||||||
|
|
||||||
|
c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
||||||
|
|
||||||
|
c.action do |args, options|
|
||||||
|
Jekyll::Commands::Doctor.process(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def process(options)
|
def process(options)
|
||||||
site = Jekyll::Site.new(options)
|
site = Jekyll::Site.new(configuration_from_options(options))
|
||||||
site.read
|
site.read
|
||||||
|
|
||||||
if healthy?(site)
|
if healthy?(site)
|
||||||
|
@ -61,7 +76,9 @@ module Jekyll
|
||||||
end
|
end
|
||||||
urls
|
urls
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,23 +3,36 @@ require 'erb'
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module Commands
|
module Commands
|
||||||
class New < Command
|
class New < Command
|
||||||
|
def self.init_with_program(prog)
|
||||||
|
prog.command(:new) do |c|
|
||||||
|
c.syntax 'new PATH'
|
||||||
|
c.description 'Creates a new Jekyll site scaffold in PATH'
|
||||||
|
|
||||||
|
c.option 'force', '--force', 'Force creation even if PATH already exists'
|
||||||
|
c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
|
||||||
|
|
||||||
|
c.action do |args, options|
|
||||||
|
Jekyll::Commands::New.process(args, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.process(args, options = {})
|
def self.process(args, options = {})
|
||||||
raise ArgumentError.new('You must specify a path.') if args.empty?
|
raise ArgumentError.new('You must specify a path.') if args.empty?
|
||||||
|
|
||||||
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
||||||
FileUtils.mkdir_p new_blog_path
|
FileUtils.mkdir_p new_blog_path
|
||||||
if preserve_source_location?(new_blog_path, options)
|
if preserve_source_location?(new_blog_path, options)
|
||||||
Jekyll.logger.error "Conflict:", "#{new_blog_path} exists and is not empty."
|
Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
|
||||||
exit(1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if options[:blank]
|
if options["blank"]
|
||||||
create_blank_site new_blog_path
|
create_blank_site new_blog_path
|
||||||
else
|
else
|
||||||
create_sample_files new_blog_path
|
create_sample_files new_blog_path
|
||||||
|
|
||||||
File.open(File.expand_path(self.initialized_post_name, new_blog_path), "w") do |f|
|
File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
|
||||||
f.write(self.scaffold_post_content)
|
f.write(scaffold_post_content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -47,7 +60,7 @@ module Jekyll
|
||||||
private
|
private
|
||||||
|
|
||||||
def self.preserve_source_location?(path, options)
|
def self.preserve_source_location?(path, options)
|
||||||
!options[:force] && !Dir["#{path}/**/*"].empty?
|
!options["force"] && !Dir["#{path}/**/*"].empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create_sample_files(path)
|
def self.create_sample_files(path)
|
||||||
|
|
|
@ -2,76 +2,105 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module Commands
|
module Commands
|
||||||
class Serve < Command
|
class Serve < Command
|
||||||
def self.process(options)
|
|
||||||
require 'webrick'
|
|
||||||
include WEBrick
|
|
||||||
|
|
||||||
destination = options['destination']
|
class << self
|
||||||
|
|
||||||
FileUtils.mkdir_p(destination)
|
def init_with_program(prog)
|
||||||
|
prog.command(:serve) do |c|
|
||||||
|
c.syntax 'serve [options]'
|
||||||
|
c.description 'Serve your site locally'
|
||||||
|
c.alias :server
|
||||||
|
|
||||||
# monkey patch WEBrick using custom 404 page (/404.html)
|
add_build_options(c)
|
||||||
if File.exists?(File.join(destination, '404.html'))
|
|
||||||
WEBrick::HTTPResponse.class_eval do
|
c.option 'detach', '-B', '--detach', 'Run the server in the background (detach)'
|
||||||
def create_error_page
|
c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
|
||||||
@body = IO.read(File.join(@config[:DocumentRoot], '404.html'))
|
c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
|
||||||
|
c.option 'baseurl', '-b', '--baseurl [URL]', 'Base URL'
|
||||||
|
|
||||||
|
c.action do |args, options|
|
||||||
|
options["serving"] ||= true
|
||||||
|
Jekyll::Commands::Build.process(options)
|
||||||
|
Jekyll::Commands::Serve.process(options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# recreate NondisclosureName under utf-8 circumstance
|
# Boot up a WEBrick server which points to the compiled site's root.
|
||||||
fh_option = WEBrick::Config::FileHandler
|
def process(options)
|
||||||
fh_option[:NondisclosureName] = ['.ht*','~*']
|
options = configuration_from_options(options)
|
||||||
|
|
||||||
s = HTTPServer.new(webrick_options(options))
|
require 'webrick'
|
||||||
|
|
||||||
s.config.store(:DirectoryIndex, s.config[:DirectoryIndex] << "index.xml")
|
destination = options['destination']
|
||||||
|
|
||||||
s.mount(options['baseurl'], HTTPServlet::FileHandler, destination, fh_option)
|
FileUtils.mkdir_p(destination)
|
||||||
|
|
||||||
Jekyll.logger.info "Server address:", "http://#{s.config[:BindAddress]}:#{s.config[:Port]}"
|
# monkey patch WEBrick using custom 404 page (/404.html)
|
||||||
|
if File.exists?(File.join(destination, '404.html'))
|
||||||
|
WEBrick::HTTPResponse.class_eval do
|
||||||
|
def create_error_page
|
||||||
|
@body = IO.read(File.join(@config[:DocumentRoot], '404.html'))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if options['detach'] # detach the server
|
# recreate NondisclosureName under utf-8 circumstance
|
||||||
pid = Process.fork { s.start }
|
fh_option = WEBrick::Config::FileHandler
|
||||||
Process.detach(pid)
|
fh_option[:NondisclosureName] = ['.ht*','~*']
|
||||||
Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
|
|
||||||
else # create a new server thread, then join it with current terminal
|
|
||||||
t = Thread.new { s.start }
|
|
||||||
trap("INT") { s.shutdown }
|
|
||||||
t.join()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.webrick_options(config)
|
s = WEBrick::HTTPServer.new(webrick_options(options))
|
||||||
opts = {
|
|
||||||
:DocumentRoot => config['destination'],
|
|
||||||
:Port => config['port'],
|
|
||||||
:BindAddress => config['host'],
|
|
||||||
:MimeTypes => self.mime_types,
|
|
||||||
:DoNotReverseLookup => true,
|
|
||||||
:StartCallback => start_callback(config['detach'])
|
|
||||||
}
|
|
||||||
|
|
||||||
if !config['verbose']
|
s.config.store(:DirectoryIndex, s.config[:DirectoryIndex] << "index.xml")
|
||||||
opts.merge!({
|
|
||||||
:AccessLog => [],
|
s.mount(options['baseurl'], WEBrick::HTTPServlet::FileHandler, destination, fh_option)
|
||||||
:Logger => Log::new([], Log::WARN)
|
|
||||||
})
|
Jekyll.logger.info "Server address:", "http://#{s.config[:BindAddress]}:#{s.config[:Port]}"
|
||||||
|
|
||||||
|
if options['detach'] # detach the server
|
||||||
|
pid = Process.fork { s.start }
|
||||||
|
Process.detach(pid)
|
||||||
|
Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
|
||||||
|
else # create a new server thread, then join it with current terminal
|
||||||
|
t = Thread.new { s.start }
|
||||||
|
trap("INT") { s.shutdown }
|
||||||
|
t.join
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
opts
|
def webrick_options(config)
|
||||||
end
|
opts = {
|
||||||
|
:DocumentRoot => config['destination'],
|
||||||
|
:Port => config['port'],
|
||||||
|
:BindAddress => config['host'],
|
||||||
|
:MimeTypes => mime_types,
|
||||||
|
:DoNotReverseLookup => true,
|
||||||
|
:StartCallback => start_callback(config['detach'])
|
||||||
|
}
|
||||||
|
|
||||||
def self.start_callback(detached)
|
if !config['verbose']
|
||||||
unless detached
|
opts.merge!({
|
||||||
Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
|
:AccessLog => [],
|
||||||
|
:Logger => WEBrick::Log.new([], WEBrick::Log::WARN)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def start_callback(detached)
|
||||||
|
unless detached
|
||||||
|
Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def mime_types
|
||||||
|
mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
|
||||||
|
WEBrick::HTTPUtils::load_mime_types(mime_types_file)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.mime_types
|
|
||||||
mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
|
|
||||||
WEBrick::HTTPUtils::load_mime_types(mime_types_file)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue