#!/usr/bin/env ruby $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib]) help = < ./_site jekyll # . -> jekyll # -> jekyll import # imports posts using named import script Configuration is read from '/_config.yml' but can be overriden using the following options: HELP require 'optparse' require 'jekyll' exec = {} options = {} opts = OptionParser.new do |opts| opts.banner = help opts.on("--file [PATH]", "File to import from") do |import_file| options['file'] = import_file end opts.on("--dbname [TEXT]", "DB to import from") do |import_dbname| options['dbname'] = import_dbname end opts.on("--user [TEXT]", "Username to use when importing") do |import_user| options['user'] = import_user end opts.on("--pass [TEXT]", "Password to use when importing") do |import_pass| options['pass'] = import_pass end opts.on("--host [HOST ADDRESS]", "Host to import from") do |import_host| options['host'] = import_host end opts.on("--site [SITE NAME]", "Site to import from") do |import_site| options['site'] = import_site end opts.on("--[no-]safe", "Safe mode (default unsafe)") do |safe| options['safe'] = safe end opts.on("--[no-]auto", "Auto-regenerate") do |auto| options['auto'] = auto end opts.on("--server [PORT]", "Start web server (default port 4000)") do |port| options['server'] = true options['server_port'] = port unless port.nil? end opts.on("--no-server", "Do not start a web server") do |part| options['server'] = false end opts.on("--base-url [BASE_URL]", "Serve website from a given base URL (default '/'") do |baseurl| options['baseurl'] = baseurl end opts.on("--default-mimetype [MT]", "Mimetype to use when no file extension (if --server)") do |mt| options['default-mimetype'] = mt end opts.on("--[no-]lsi", "Use LSI for better related posts") do |lsi| options['lsi'] = lsi end opts.on("--[no-]pygments", "Use pygments to highlight code") do |pygments| options['pygments'] = pygments end opts.on("--rdiscount", "Use rdiscount gem for Markdown") do options['markdown'] = 'rdiscount' end opts.on("--redcarpet", "Use redcarpet gem for Markdown") do options['markdown'] = 'redcarpet' end opts.on("--kramdown", "Use kramdown gem for Markdown") do options['markdown'] = 'kramdown' end opts.on("--time [TIME]", "Time to generate the site for") do |time| options['time'] = Time.parse(time) end opts.on("--[no-]future", "Render future dated posts") do |future| options['future'] = future end opts.on("--permalink [TYPE]", "Use 'date' (default) for YYYY/MM/DD") do |style| options['permalink'] = style unless style.nil? end opts.on("--paginate [POSTS_PER_PAGE]", "Paginate a blog's posts") do |per_page| begin options['paginate'] = per_page.to_i raise ArgumentError if options['paginate'] == 0 rescue puts 'you must specify a number of posts by page bigger than 0' exit 0 end end opts.on("--limit_posts [MAX_POSTS]", "Limit the number of posts to publish") do |limit_posts| begin options['limit_posts'] = limit_posts.to_i raise ArgumentError if options['limit_posts'] < 1 rescue puts 'you must specify a number of posts by page bigger than 0' exit 0 end end opts.on("--preview", "Publish posts that are from the future or marked unpublished") do options['preview'] = true end opts.on("--url [URL]", "Set custom site.url") do |url| options['url'] = url end opts.on("--version", "Display current version") do puts "Jekyll " + Jekyll::VERSION exit 0 end end # Read command line options into `options` hash opts.parse! # Check for import stuff if ARGV.size > 0 if ARGV[0] == 'import' migrator = ARGV[1] if migrator.nil? puts "Invalid options. Run `jekyll --help` for assistance." exit(1) else migrator = migrator.downcase end cmd_options = [] ['file', 'dbname', 'user', 'pass', 'host', 'site'].each do |p| cmd_options << "\"#{options[p]}\"" unless options[p].nil? end # It's import time puts "Importing..." # Ideally, this shouldn't be necessary. Maybe parse the actual # src files for the migrator name? migrators = { :posterous => 'Posterous', :wordpressdotcom => 'WordpressDotCom', :wordpress => 'WordPress', :csv => 'CSV', :drupal => 'Drupal', :enki => 'Enki', :mephisto => 'Mephisto', :mt => 'MT', :textpattern => 'TextPattern', :tumblr => 'Tumblr', :typo => 'Typo' } app_root = File.join(File.dirname(__FILE__), '..') require "#{app_root}/lib/jekyll/migrators/#{migrator}" if Jekyll.const_defined?(migrators[migrator.to_sym]) migrator_class = Jekyll.const_get(migrators[migrator.to_sym]) migrator_class.process(*cmd_options) else puts "Invalid migrator. Run `jekyll --help` for assistance." exit(1) end exit(0) end end # Get source and destination from command line case ARGV.size when 0 when 1 options['destination'] = ARGV[0] when 2 options['source'] = ARGV[0] options['destination'] = ARGV[1] else puts "Invalid options. Run `jekyll --help` for assistance." exit(1) end options = Jekyll.configuration(options) # Get source and destination directories (possibly set by config file) source = options['source'] destination = options['destination'] # Files to watch def globs(source) Dir.chdir(source) do dirs = Dir['*'].select { |x| File.directory?(x) } dirs -= ['_site'] dirs = dirs.map { |x| "#{x}/**/*" } dirs += ['*'] end end # Create the Site site = Jekyll::Site.new(options) # Run the directory watcher for auto-generation, if required if options['auto'] require 'directory_watcher' puts "Auto-regenerating enabled: #{source} -> #{destination}" dw = DirectoryWatcher.new(source) dw.interval = 1 dw.glob = globs(source) dw.add_observer do |*args| t = Time.now.strftime("%Y-%m-%d %H:%M:%S") puts "[#{t}] regeneration: #{args.size} files changed" site.process end dw.start unless options['server'] loop { sleep 1000 } end else puts "Building site: #{source} -> #{destination}" begin site.process rescue Jekyll::FatalException => e puts puts "ERROR: YOUR SITE COULD NOT BE BUILT:" puts "------------------------------------" puts e.message exit(1) end puts "Successfully generated site: #{source} -> #{destination}" end # Run the server on the specified port, if required if options['server'] require 'webrick' include WEBrick FileUtils.mkdir_p(destination) mime_types = WEBrick::HTTPUtils::DefaultMimeTypes mime_types.store 'js', 'application/javascript' if options['default-mimetype'] mime_types.store(nil, options['default-mimetype']) end s = HTTPServer.new( :Port => options['server_port'], :MimeTypes => mime_types ) s.mount(options['baseurl'], HTTPServlet::FileHandler, destination) t = Thread.new { s.start } trap("INT") { s.shutdown } t.join() end