Merge pull request #2143 from jekyll/fix-cli
This commit is contained in:
		
						commit
						a581bc158b
					
				
							
								
								
									
										122
									
								
								bin/jekyll
								
								
								
								
							
							
						
						
									
										122
									
								
								bin/jekyll
								
								
								
								
							| 
						 | 
				
			
			@ -6,19 +6,15 @@ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
 | 
			
		|||
require 'jekyll'
 | 
			
		||||
require 'mercenary'
 | 
			
		||||
 | 
			
		||||
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.'
 | 
			
		||||
%w[jekyll-import].each do |blessed_gem|
 | 
			
		||||
  begin
 | 
			
		||||
    require blessed_gem
 | 
			
		||||
  rescue LoadError
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Jekyll::Deprecator.process(ARGV)
 | 
			
		||||
 | 
			
		||||
Mercenary.program(:jekyll) do |p|
 | 
			
		||||
  p.version Jekyll::VERSION
 | 
			
		||||
  p.description 'Jekyll is a blog-aware, static site generator in Ruby'
 | 
			
		||||
| 
						 | 
				
			
			@ -30,113 +26,15 @@ Mercenary.program(:jekyll) do |p|
 | 
			
		|||
  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)'
 | 
			
		||||
 | 
			
		||||
  Jekyll::Command.subclasses.each { |c| c.init_with_program(p) }
 | 
			
		||||
 | 
			
		||||
  p.action do |args, options|
 | 
			
		||||
    if args.empty?
 | 
			
		||||
      p.go(["-h"])
 | 
			
		||||
      puts p
 | 
			
		||||
    else
 | 
			
		||||
      unless p.has_command?(args.first)
 | 
			
		||||
        Jekyll.logger.abort_with "Invalid command. Use --help for more information"
 | 
			
		||||
      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|
 | 
			
		||||
    c.syntax 'jekyll import <platform> [options]'
 | 
			
		||||
    c.description 'Import your old blog to Jekyll'
 | 
			
		||||
    importers = []
 | 
			
		||||
 | 
			
		||||
    begin
 | 
			
		||||
      require 'jekyll-import'
 | 
			
		||||
      importers = JekyllImport.add_importer_commands(c)
 | 
			
		||||
    rescue LoadError
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    c.action do |args, options|
 | 
			
		||||
      unless Object.const_defined?(:JekyllImport)
 | 
			
		||||
        msg  = "You must install the 'jekyll-import' gem before continuing.\n"
 | 
			
		||||
        msg += "* Please see the documentation at http://jekyllrb.com/docs/migrations/ for instructions.\n"
 | 
			
		||||
        abort msg
 | 
			
		||||
      end
 | 
			
		||||
      if args.empty?
 | 
			
		||||
        Jekyll.logger.warn "You must specify an importer."
 | 
			
		||||
        Jekyll.logger.info "Valid options are:"
 | 
			
		||||
        importers.each { |i| Jekyll.logger.info "*", "#{i}" }
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,27 +1,79 @@
 | 
			
		|||
module Jekyll
 | 
			
		||||
  class Command
 | 
			
		||||
    def self.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 += ['*']
 | 
			
		||||
 | 
			
		||||
    class << self
 | 
			
		||||
 | 
			
		||||
      # A list of subclasses of Jekyll::Command
 | 
			
		||||
      def subclasses
 | 
			
		||||
        @subclasses ||= []
 | 
			
		||||
      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
 | 
			
		||||
 | 
			
		||||
    # 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,72 +1,96 @@
 | 
			
		|||
module Jekyll
 | 
			
		||||
  module Commands
 | 
			
		||||
    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)
 | 
			
		||||
        watch(site, options) if options['watch']
 | 
			
		||||
      end
 | 
			
		||||
        # Create the Mercenary command for the Jekyll CLI for this Command
 | 
			
		||||
        def init_with_program(prog)
 | 
			
		||||
          prog.command(:build) do |c|
 | 
			
		||||
            c.syntax      'build [options]'
 | 
			
		||||
            c.description 'Build your site'
 | 
			
		||||
 | 
			
		||||
      # Private: Build the site from source into destination.
 | 
			
		||||
      #
 | 
			
		||||
      # 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
 | 
			
		||||
            add_build_options(c)
 | 
			
		||||
 | 
			
		||||
      # Private: Watch for file changes and rebuild the site.
 | 
			
		||||
      #
 | 
			
		||||
      # site - A Jekyll::Site instance
 | 
			
		||||
      # options - A Hash of options passed to the command
 | 
			
		||||
      #
 | 
			
		||||
      # 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
 | 
			
		||||
            c.action do |args, options|
 | 
			
		||||
              options["serving"] = false
 | 
			
		||||
              Jekyll::Commands::Build.process(options)
 | 
			
		||||
            end
 | 
			
		||||
          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|
 | 
			
		||||
          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} "
 | 
			
		||||
          Jekyll.logger.log_level = Jekyll::Stevenson::ERROR if options['quiet']
 | 
			
		||||
 | 
			
		||||
          build(site, options)
 | 
			
		||||
          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)
 | 
			
		||||
          puts  "...done."
 | 
			
		||||
          Jekyll.logger.info "", "done."
 | 
			
		||||
        end
 | 
			
		||||
        listener.start
 | 
			
		||||
 | 
			
		||||
        unless options['serving']
 | 
			
		||||
          trap("INT") do
 | 
			
		||||
            listener.stop
 | 
			
		||||
            puts "     Halting auto-regeneration."
 | 
			
		||||
            exit 0
 | 
			
		||||
        # Private: Watch for file changes and rebuild the site.
 | 
			
		||||
        #
 | 
			
		||||
        # site - A Jekyll::Site instance
 | 
			
		||||
        # options - A Hash of options passed to the command
 | 
			
		||||
        #
 | 
			
		||||
        # 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
 | 
			
		||||
 | 
			
		||||
          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 of class << self
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
    class Doctor < Command
 | 
			
		||||
      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)
 | 
			
		||||
          site = Jekyll::Site.new(options)
 | 
			
		||||
          site = Jekyll::Site.new(configuration_from_options(options))
 | 
			
		||||
          site.read
 | 
			
		||||
 | 
			
		||||
          if healthy?(site)
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +76,9 @@ module Jekyll
 | 
			
		|||
          end
 | 
			
		||||
          urls
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,23 +3,36 @@ require 'erb'
 | 
			
		|||
module Jekyll
 | 
			
		||||
  module Commands
 | 
			
		||||
    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 = {})
 | 
			
		||||
        raise ArgumentError.new('You must specify a path.') if args.empty?
 | 
			
		||||
 | 
			
		||||
        new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
 | 
			
		||||
        FileUtils.mkdir_p new_blog_path
 | 
			
		||||
        if preserve_source_location?(new_blog_path, options)
 | 
			
		||||
          Jekyll.logger.error "Conflict:", "#{new_blog_path} exists and is not empty."
 | 
			
		||||
          exit(1)
 | 
			
		||||
          Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if options[:blank]
 | 
			
		||||
        if options["blank"]
 | 
			
		||||
          create_blank_site new_blog_path
 | 
			
		||||
        else
 | 
			
		||||
          create_sample_files new_blog_path
 | 
			
		||||
 | 
			
		||||
          File.open(File.expand_path(self.initialized_post_name, new_blog_path), "w") do |f|
 | 
			
		||||
            f.write(self.scaffold_post_content)
 | 
			
		||||
          File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
 | 
			
		||||
            f.write(scaffold_post_content)
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +60,7 @@ module Jekyll
 | 
			
		|||
      private
 | 
			
		||||
 | 
			
		||||
      def self.preserve_source_location?(path, options)
 | 
			
		||||
        !options[:force] && !Dir["#{path}/**/*"].empty?
 | 
			
		||||
        !options["force"] && !Dir["#{path}/**/*"].empty?
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def self.create_sample_files(path)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,76 +2,105 @@
 | 
			
		|||
module Jekyll
 | 
			
		||||
  module Commands
 | 
			
		||||
    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)
 | 
			
		||||
        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'))
 | 
			
		||||
            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
 | 
			
		||||
              Jekyll::Commands::Build.process(options)
 | 
			
		||||
              Jekyll::Commands::Serve.process(options)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        # recreate NondisclosureName under utf-8 circumstance
 | 
			
		||||
        fh_option = WEBrick::Config::FileHandler
 | 
			
		||||
        fh_option[:NondisclosureName] = ['.ht*','~*']
 | 
			
		||||
        # Boot up a WEBrick server which points to the compiled site's root.
 | 
			
		||||
        def process(options)
 | 
			
		||||
          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
 | 
			
		||||
          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
 | 
			
		||||
          # recreate NondisclosureName under utf-8 circumstance
 | 
			
		||||
          fh_option = WEBrick::Config::FileHandler
 | 
			
		||||
          fh_option[:NondisclosureName] = ['.ht*','~*']
 | 
			
		||||
 | 
			
		||||
      def self.webrick_options(config)
 | 
			
		||||
        opts = {
 | 
			
		||||
          :DocumentRoot => config['destination'],
 | 
			
		||||
          :Port => config['port'],
 | 
			
		||||
          :BindAddress => config['host'],
 | 
			
		||||
          :MimeTypes => self.mime_types,
 | 
			
		||||
          :DoNotReverseLookup => true,
 | 
			
		||||
          :StartCallback => start_callback(config['detach'])
 | 
			
		||||
        }
 | 
			
		||||
          s = WEBrick::HTTPServer.new(webrick_options(options))
 | 
			
		||||
 | 
			
		||||
        if !config['verbose']
 | 
			
		||||
          opts.merge!({
 | 
			
		||||
            :AccessLog => [],
 | 
			
		||||
            :Logger => Log::new([], Log::WARN)
 | 
			
		||||
          })
 | 
			
		||||
          s.config.store(:DirectoryIndex, s.config[:DirectoryIndex] << "index.xml")
 | 
			
		||||
 | 
			
		||||
          s.mount(options['baseurl'], WEBrick::HTTPServlet::FileHandler, destination, fh_option)
 | 
			
		||||
 | 
			
		||||
          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
 | 
			
		||||
 | 
			
		||||
        opts
 | 
			
		||||
      end
 | 
			
		||||
        def webrick_options(config)
 | 
			
		||||
          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)
 | 
			
		||||
        unless detached
 | 
			
		||||
          Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
 | 
			
		||||
          if !config['verbose']
 | 
			
		||||
            opts.merge!({
 | 
			
		||||
              :AccessLog => [],
 | 
			
		||||
              :Logger => WEBrick::Log.new([], WEBrick::Log::WARN)
 | 
			
		||||
            })
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          opts
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
      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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue