lib/guard/jekyll-plus.rb in guard-jekyll-plus-1.4.10 vs lib/guard/jekyll-plus.rb in guard-jekyll-plus-2.0.0

- old
+ new

@@ -1,93 +1,96 @@ # encoding: UTF-8 -require 'guard' -require 'guard/guard' +require 'benchmark' +require 'guard/plugin' require 'jekyll' begin require 'rack' - @use_rack = true rescue LoadError end module Guard - class Jekyllplus < Guard - - def initialize (watchers=[], options={}) + class Jekyllplus < Plugin + def initialize(options = {}) super - default_extensions = ['md','mkd','mkdn','markdown','textile','html','haml','slim','xml','yml'] + default_extensions = ['md','mkd','mkdn','markdown','textile','html','haml','slim','xml','yml','sass','scss'] @options = { - :extensions => [], + :extensions => [], :config => ['_config.yml'], :serve => false, :rack_config => nil, :drafts => false, :future => false, :config_hash => nil, :silent => false, :msg_prefix => 'Jekyll' }.merge(options) - # The config_hash option should be a hash ready to be consumed by Jekyll's Site class. - # - @config = jekyll_config(@options) - - # Override configuration with guard option values - # - @config['show_drafts'] ||= @options[:drafts] - @config['future'] ||= @options[:future] - - # Store vars for easy internal access - # + @config = load_config(@options) @source = local_path @config['source'] @destination = local_path @config['destination'] @msg_prefix = @options[:msg_prefix] - + # Convert array of extensions into a regex for matching file extensions eg, /\.md$|\.markdown$|\.html$/i - # + # extensions = @options[:extensions].concat(default_extensions).flatten.uniq @extensions = Regexp.new extensions.map { |e| (e << '$').gsub('\.', '\\.') }.join('|'), true - # set Jekyll server process id to nil - # - @pid = nil + # set Jekyll server thread to nil + @server_thread = nil - # Create a Jekyll site - # - @site = ::Jekyll::Site.new @config - @rack = ::Rack::Server.new(rack_config(@destination)) if @use_rack + end + def load_config(options) + config = jekyll_config(options) + + # Override configuration with guard option values + config['show_drafts'] ||= options[:drafts] + config['future'] ||= options[:future] + config end + def reload_config! + UI.info "Reloading Jekyll configuration!" + @config = load_config(@options) + end + def start if @options[:serve] - start_server build + start_server UI.info "#{@msg_prefix} " + "watching and serving at #{@config['host']}:#{@config['port']}#{@config['baseurl']}" unless @config[:silent] else build UI.info "#{@msg_prefix} " + "watching" unless @config[:silent] end end - def restart - stop if alive? + def reload + stop if !@server_thread.nil? and @server_thread.alive? + reload_config! start end + def reload_server + stop_server + start_server + end def stop stop_server end def run_on_modifications(paths) + # At this point we know @options[:config] is going to be an Array + # thanks to the call the jekyll_config earlier. + reload_config! if @options[:config].map { |f| paths.include?(f) }.any? matched = jekyll_matches paths unmatched = non_jekyll_matches paths - if matched.size > 0 build(matched, "Files changed: ", " ~ ".yellow) elsif unmatched.size > 0 copy(unmatched) end @@ -124,14 +127,13 @@ if files puts '| ' # spacing files.each { |file| puts '|' + mark + file } puts '| ' # spacing end - @site.process - UI.info "#{@msg_prefix} " + "build complete ".green + "#{@source} → #{@destination}" unless @config[:silent] - - rescue Exception => e + elapsed = Benchmark.realtime { build_site(@config) } + UI.info "#{@msg_prefix} " + "build completed in #{elapsed.round(2)}s ".green + "#{@source} → #{@destination}" unless @config[:silent] + rescue Exception UI.error "#{@msg_prefix} build has failed" unless @config[:silent] stop_server throw :task_has_failed end end @@ -145,18 +147,22 @@ message = 'copied file' message += 's' if files.size > 1 UI.info "#{@msg_prefix} #{message.green}" unless @config[:silent] puts '| ' #spacing files.each do |file| - path = destination_path file - FileUtils.mkdir_p File.dirname(path) - FileUtils.cp file, path - puts '|' + " → ".green + path + if(!check_jekyll_exclude(file)) + path = destination_path file + FileUtils.mkdir_p File.dirname(path) + FileUtils.cp file, path + puts '|' + " → ".green + path + else + puts '|' + " ~ ".yellow + "Jekyll exclude: Ignoring changes to #{file}".yellow + end end puts '| ' #spacing - rescue Exception => e + rescue Exception UI.error "#{@msg_prefix} copy has failed" unless @config[:silent] UI.error e stop_server throw :task_has_failed end @@ -169,11 +175,11 @@ ignore = ENV['GUARD_STITCH_PLUS_FILES'].split(',') files.reject {|f| ignore.include? f } else files end - + end # Remove deleted source file/directories from destination # def remove(files=[]) @@ -193,17 +199,17 @@ puts '|' + " x ".red + path end dir = File.dirname path if Dir[dir+'/*'].empty? - FileUtils.rm_r(dir) + FileUtils.rm_r(dir) puts '|' + " x ".red + dir end end puts '| ' #spacing - rescue Exception => e + rescue Exception UI.error "#{@msg_prefix} remove has failed" unless @config[:silent] UI.error e stop_server throw :task_has_failed end @@ -224,80 +230,71 @@ config = options[:config_hash] elsif options[:config] options[:config] = [options[:config]] unless options[:config].is_a? Array config = options end - ::Jekyll.configuration(config) + Jekyll.configuration(config) end + def check_jekyll_exclude(path) + return @config['exclude'].any? {|f| File.fnmatch?(path, f)} + end + def rack_config(root) ENV['RACK_ROOT'] = root default_config = File.expand_path("../rack/config.ru", File.dirname(__FILE__)) local_config = File.exist?('config.ru') ? 'config.ru' : nil config = (@config['rack_config'] || local_config || default_config) - { :config => config, :Port => @config['port'], :Host => @config['host'] } + { :config => config, :Port => @config['port'], :Host => @config['host'], :environment => 'development' } end def local_path(path) Dir.chdir('.') current = Dir.pwd path = path.sub current, '' if path == '' './' - else - path.sub /^\//, '' + else + path.sub(/^\//, '') end end + + def build_site(options) + Jekyll.logger.log_level = :error + site = Jekyll::Site.new(options) + Jekyll.logger.log_level = :info + site.process + end + def destination_path(file) if @source =~ /^\./ File.join @destination, file else - file.sub /^#{@source}/, "#{@destination}" + file.sub(/^#{@source}/, "#{@destination}") end end - # Remove - def ignore_underscores(paths) - paths.select { |file| file =~ /^[^_]/ } - end - def server(config) - if @rack - proc{ Process.fork { @rack.start } } + if defined? ::Rack + Thread.new { ::Rack::Server.start(rack_config(@destination)) } + UI.info "#{@msg_prefix} running Rack" unless @config[:silent] else - proc{ Process.fork { ::Jekyll::Commands::Serve.process(config) } } + Thread.new { Jekyll::Commands::Serve.process(config) } end end - def kill - proc{|pid| Process.kill("INT", pid)} - end - def start_server - return @pid if alive? - @pid = instance_eval &server(@config) + if @server_thread.nil? + @server_thread = server(@config) + else + UI.warning "#{@msg_prefix} using an old server thread!" + end end def stop_server - if alive? - instance_eval do - kill.call(@pid) - @pid = nil - end - end + @server_thread.kill unless @server_thread.nil? + @server_thread = nil end - - def alive? - return false unless @pid - - begin - Process.getpgid(@pid) - true - rescue Errno::ESRCH => e - false - end - end end end -