Merge pull request #690 from tombell/jekyll-command-redux
The Big Jekyll Command Cleanup
This commit is contained in:
commit
14cabab254
325
bin/jekyll
325
bin/jekyll
|
@ -1,303 +1,70 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
$:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
|
||||||
|
|
||||||
help = <<HELP
|
require 'commander/import'
|
||||||
Jekyll is a blog-aware, static site generator.
|
|
||||||
|
|
||||||
Basic Command Line Usage:
|
|
||||||
jekyll # . -> ./_site
|
|
||||||
jekyll <path to write generated site> # . -> <path>
|
|
||||||
jekyll <path to source> <path to write generated site> # <path> -> <path>
|
|
||||||
jekyll import <importer name> <options> # imports posts using named import script
|
|
||||||
|
|
||||||
Configuration is read from '<source>/_config.yml' but can be overriden
|
|
||||||
using the following options:
|
|
||||||
|
|
||||||
HELP
|
|
||||||
|
|
||||||
require 'optparse'
|
|
||||||
require 'jekyll'
|
require 'jekyll'
|
||||||
|
|
||||||
|
program :name, 'jekyll'
|
||||||
|
program :version, Jekyll::VERSION
|
||||||
|
program :description, 'Jekyll is a blog-aware, static site generator in Ruby'
|
||||||
|
|
||||||
exec = {}
|
default_command :help
|
||||||
options = {}
|
|
||||||
opts = OptionParser.new do |opts|
|
|
||||||
opts.banner = help
|
|
||||||
|
|
||||||
opts.on("--file [PATH]", "File to import from") do |import_file|
|
global_option '-s', '--source [DIR]', 'Source directory (defaults to ./)'
|
||||||
options['file'] = import_file
|
global_option '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
|
||||||
end
|
global_option '--safe', 'Safe mode (defaults to false)'
|
||||||
|
global_option '--plugins', 'Plugins directory (defaults to ./_plugins)'
|
||||||
opts.on("--dbname [TEXT]", "DB to import from") do |import_dbname|
|
global_option '--layouts', 'Layouts directory (defaults to ./_layouts)'
|
||||||
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|
|
command :build do |c|
|
||||||
options['safe'] = safe
|
c.syntax = 'jekyll build [options]'
|
||||||
end
|
c.description = 'Build your site with the option of auto-renegeration'
|
||||||
|
|
||||||
opts.on("--[no-]auto", "Auto-regenerate") do |auto|
|
c.option '-w', '--watch', 'Watch for changes and rebuild'
|
||||||
options['auto'] = auto
|
c.option '--lsi', 'Use LSI for improved related posts'
|
||||||
end
|
|
||||||
|
|
||||||
opts.on("--server [PORT]", "Start web server (default port 4000)") do |port|
|
c.action do |args, options|
|
||||||
options['server'] = true
|
options.defaults :serving => false
|
||||||
options['server_port'] = port unless port.nil?
|
options = Jekyll.configuration(options.__hash__)
|
||||||
end
|
Jekyll::BuildCommand.process(options)
|
||||||
|
|
||||||
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("--paginate_path [PAGINATED_URL_FORMAT]", "Leave blank for /page<num>") do |paginate_path|
|
|
||||||
begin
|
|
||||||
options['paginate_path'] = paginate_path
|
|
||||||
raise ArgumentError if options['paginate_path'].nil?
|
|
||||||
rescue
|
|
||||||
puts 'You must specify a pagination url format'
|
|
||||||
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("--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
|
|
||||||
|
|
||||||
opts.on( "--keep-files filename1,filename2", Array, "Whether to keep files that match the filename (default: .git)") do |names|
|
|
||||||
options['keep_files'] = names
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read command line options into `options` hash
|
command :serve do |c|
|
||||||
opts.parse!
|
c.syntax = 'jekyll serve [options]'
|
||||||
|
c.description = 'Serve your site locally with the option of auto-regeneration'
|
||||||
|
|
||||||
|
c.option '-w', '--watch', 'Watch for changes and rebuild'
|
||||||
|
c.option '--lsi', 'Use LSI for improved related posts'
|
||||||
|
|
||||||
# Check for import stuff
|
c.option '-p', '--port [PORT]', 'Port to listen on'
|
||||||
if ARGV.size > 0
|
c.option '-h', '--host [HOST]', 'Host to bind to'
|
||||||
if ARGV[0] == 'import'
|
c.option '-b', '--baseurl [URL]', 'Base URL'
|
||||||
migrator = ARGV[1]
|
|
||||||
|
|
||||||
if migrator.nil?
|
c.action do |args, options|
|
||||||
puts "Invalid options. Run `jekyll --help` for assistance."
|
options.default :port => '4000',
|
||||||
exit(1)
|
:host => '0.0.0.0',
|
||||||
else
|
:baseurl => '/',
|
||||||
migrator = migrator.downcase
|
:serving => true
|
||||||
end
|
|
||||||
|
|
||||||
cmd_options = []
|
options = Jekyll.configuration(options.__hash__)
|
||||||
['file', 'dbname', 'user', 'pass', 'host', 'site'].each do |p|
|
Jekyll::BuildCommand.process(options)
|
||||||
cmd_options << "\"#{options[p]}\"" unless options[p].nil?
|
Jekyll::ServeCommand.process(options)
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
command :import do |c|
|
||||||
|
c.syntax = 'jekyll import <platform> [options]'
|
||||||
|
c.description = 'Import your old blog to Jekyll'
|
||||||
|
|
||||||
|
c.option '--file', 'File to migrate from'
|
||||||
|
c.option '--dbname', 'Database name to migrate from'
|
||||||
|
c.option '--user', 'Username to use when migrating'
|
||||||
|
c.option '--pass', 'Password to use when migrating'
|
||||||
|
c.option '--host', 'Host address to use when migrating'
|
||||||
|
|
||||||
# Get source and destination from command line
|
c.action do |args, options|
|
||||||
case ARGV.size
|
Jekyll::MigrateCommand.process(args.first, options)
|
||||||
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, destination)
|
|
||||||
Dir.chdir(source) do
|
|
||||||
dirs = Dir['*'].select { |x| File.directory?(x) }
|
|
||||||
dirs -= [destination]
|
|
||||||
dirs = dirs.map { |x| "#{x}/**/*" }
|
|
||||||
dirs += ['*']
|
|
||||||
end
|
end
|
||||||
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, destination)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ JEKYLL_PATH = File.join(ENV['PWD'], 'bin', 'jekyll')
|
||||||
|
|
||||||
def run_jekyll(opts = {})
|
def run_jekyll(opts = {})
|
||||||
command = JEKYLL_PATH
|
command = JEKYLL_PATH
|
||||||
|
command << " build"
|
||||||
command << " >> /dev/null 2>&1" if opts[:debug].nil?
|
command << " >> /dev/null 2>&1" if opts[:debug].nil?
|
||||||
system command
|
system command
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,6 +29,7 @@ Gem::Specification.new do |s|
|
||||||
s.add_runtime_dependency('maruku', "~> 0.5")
|
s.add_runtime_dependency('maruku', "~> 0.5")
|
||||||
s.add_runtime_dependency('kramdown', "~> 0.13.4")
|
s.add_runtime_dependency('kramdown', "~> 0.13.4")
|
||||||
s.add_runtime_dependency('pygments.rb', "~> 0.3.2")
|
s.add_runtime_dependency('pygments.rb', "~> 0.3.2")
|
||||||
|
s.add_runtime_dependency('commander', "~> 4.1.3")
|
||||||
|
|
||||||
s.add_development_dependency('rake', "~> 0.9")
|
s.add_development_dependency('rake', "~> 0.9")
|
||||||
s.add_development_dependency('rdoc', "~> 3.11")
|
s.add_development_dependency('rdoc', "~> 3.11")
|
||||||
|
|
|
@ -41,6 +41,9 @@ require 'jekyll/errors'
|
||||||
require 'jekyll/plugin'
|
require 'jekyll/plugin'
|
||||||
require 'jekyll/converter'
|
require 'jekyll/converter'
|
||||||
require 'jekyll/generator'
|
require 'jekyll/generator'
|
||||||
|
require 'jekyll/command'
|
||||||
|
|
||||||
|
require_all 'jekyll/commands'
|
||||||
require_all 'jekyll/converters'
|
require_all 'jekyll/converters'
|
||||||
require_all 'jekyll/generators'
|
require_all 'jekyll/generators'
|
||||||
require_all 'jekyll/tags'
|
require_all 'jekyll/tags'
|
||||||
|
@ -48,27 +51,23 @@ require_all 'jekyll/tags'
|
||||||
module Jekyll
|
module Jekyll
|
||||||
VERSION = '0.12.0'
|
VERSION = '0.12.0'
|
||||||
|
|
||||||
# Default options. Overriden by values in _config.yml or command-line opts.
|
# Default options. Overriden by values in _config.yml.
|
||||||
# Strings rather than symbols are used for compatability with YAML.
|
# Strings rather than symbols are used for compatability with YAML.
|
||||||
DEFAULTS = {
|
DEFAULTS = {
|
||||||
'safe' => false,
|
|
||||||
'auto' => false,
|
|
||||||
'server' => false,
|
|
||||||
'server_port' => 4000,
|
|
||||||
|
|
||||||
'source' => Dir.pwd,
|
'source' => Dir.pwd,
|
||||||
'destination' => File.join(Dir.pwd, '_site'),
|
'destination' => File.join(Dir.pwd, '_site'),
|
||||||
|
|
||||||
'plugins' => File.join(Dir.pwd, '_plugins'),
|
'plugins' => File.join(Dir.pwd, '_plugins'),
|
||||||
'layouts' => '_layouts',
|
'layouts' => '_layouts',
|
||||||
'keep_files' => ['.git','.svn'],
|
'keep_files' => ['.git','.svn'],
|
||||||
|
|
||||||
'future' => true,
|
'future' => true, # remove and make true just default
|
||||||
'lsi' => false,
|
'pygments' => false, # remove and make true just default
|
||||||
'pygments' => false,
|
|
||||||
'markdown' => 'maruku',
|
'markdown' => 'maruku', # no longer a command option
|
||||||
'permalink' => 'date',
|
'permalink' => 'date', # no longer a command option
|
||||||
'include' => ['.htaccess'],
|
'include' => ['.htaccess'], # no longer a command option
|
||||||
'paginate_path' => 'page:num',
|
'paginate_path' => 'page:num', # no longer a command option
|
||||||
|
|
||||||
'markdown_ext' => 'markdown,mkd,mkdn,md',
|
'markdown_ext' => 'markdown,mkd,mkdn,md',
|
||||||
'textile_ext' => 'textile',
|
'textile_ext' => 'textile',
|
||||||
|
@ -121,6 +120,9 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the final configuration Hash.
|
# Returns the final configuration Hash.
|
||||||
def self.configuration(override)
|
def self.configuration(override)
|
||||||
|
# Convert any symbol keys to strings and remove the old key/values
|
||||||
|
override = override.reduce({}) { |hsh,(k,v)| hsh.merge(k.to_s => v) }
|
||||||
|
|
||||||
# _config.yml may override default source location, but until
|
# _config.yml may override default source location, but until
|
||||||
# then, we need to know where to look for _config.yml
|
# then, we need to know where to look for _config.yml
|
||||||
source = override['source'] || Jekyll::DEFAULTS['source']
|
source = override['source'] || Jekyll::DEFAULTS['source']
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
module Jekyll
|
||||||
|
|
||||||
|
class Command
|
||||||
|
def self.globs(source)
|
||||||
|
Dir.chdir(source) do
|
||||||
|
dirs = Dir['*'].select { |x| File.directory?(x) }
|
||||||
|
dirs -= ['_site']
|
||||||
|
dirs = dirs.map { |x| "#{x}/**/*" }
|
||||||
|
dirs += ['*']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,76 @@
|
||||||
|
module Jekyll
|
||||||
|
|
||||||
|
class BuildCommand < Command
|
||||||
|
def self.process(options)
|
||||||
|
site = Jekyll::Site.new(options)
|
||||||
|
|
||||||
|
source = options['source']
|
||||||
|
destination = options['destination']
|
||||||
|
|
||||||
|
if options['watch']
|
||||||
|
self.watch(site, options)
|
||||||
|
else
|
||||||
|
self.build(site, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# 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']
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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 'directory_watcher'
|
||||||
|
|
||||||
|
source = options['source']
|
||||||
|
destination = options['destination']
|
||||||
|
|
||||||
|
puts "Auto-Regenerating enabled: #{source} -> #{destination}"
|
||||||
|
|
||||||
|
dw = DirectoryWatcher.new(source)
|
||||||
|
dw.interval = 1
|
||||||
|
dw.glob = self.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['serving']
|
||||||
|
trap("INT") do
|
||||||
|
puts "Stopping auto-regeneration..."
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
loop { sleep 1000 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,47 @@
|
||||||
|
module Jekyll
|
||||||
|
|
||||||
|
class MigrateCommand < Command
|
||||||
|
MIGRATORS = {
|
||||||
|
:csv => 'CSV',
|
||||||
|
:drupal => 'Drupal',
|
||||||
|
:enki => 'Enki',
|
||||||
|
:mephisto => 'Mephisto',
|
||||||
|
:mt => 'MT',
|
||||||
|
:posterous => 'Posterous',
|
||||||
|
:textpattern => 'TextPattern',
|
||||||
|
:tumblr => 'Tumblr',
|
||||||
|
:typo => 'Typo',
|
||||||
|
:wordpressdotcom => 'WordpressDotCom',
|
||||||
|
:wordpress => 'WordPress'
|
||||||
|
}
|
||||||
|
|
||||||
|
def self.process(migrator, options)
|
||||||
|
abort 'missing argument. Please specify a migrator' if migrator.nil?
|
||||||
|
migrator = migrator.downcase
|
||||||
|
|
||||||
|
cmd_options = []
|
||||||
|
[ :file, :dbname, :user, :pass, :host, :site ].each do |p|
|
||||||
|
cmd_options << "\"#{options[p]}\"" unless options[p].nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if MIGRATORS.keys.include?(migrator)
|
||||||
|
app_root = File.expand_path(
|
||||||
|
File.join(File.dirname(__FILE__), '..', '..', '..')
|
||||||
|
)
|
||||||
|
|
||||||
|
require "#{app_root}/lib/jekyll/migrators/#{migrator}"
|
||||||
|
|
||||||
|
if Jekyll.const_defiend?(MIGRATORS[migrator.to_sym])
|
||||||
|
puts 'Importing...'
|
||||||
|
migrator_class = Jekyll.const_get(MIGRATORS[migrator.to_sym])
|
||||||
|
migrator_class.process(*cmd_options)
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
abort 'invalid migrator. Please specify a valid migrator'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
module Jekyll
|
||||||
|
|
||||||
|
class ServeCommand < Command
|
||||||
|
def self.process(options)
|
||||||
|
require 'webrick'
|
||||||
|
include WEBrick
|
||||||
|
|
||||||
|
destination = options['destination']
|
||||||
|
|
||||||
|
FileUtils.mkdir_p(destination)
|
||||||
|
|
||||||
|
mime_types = WEBrick::HTTPUtils::DefaultMimeTypes
|
||||||
|
mime_types.store 'js', 'application/javascript'
|
||||||
|
|
||||||
|
s = HTTPServer.new(
|
||||||
|
:Port => options['port'],
|
||||||
|
:BindAddress => options['host'],
|
||||||
|
:MimeTypes => mime_types
|
||||||
|
)
|
||||||
|
|
||||||
|
s.mount(options['baseurl'], HTTPServlet::FileHandler, destination)
|
||||||
|
t = Thread.new { s.start }
|
||||||
|
trap("INT") { s.shutdown }
|
||||||
|
t.join()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,14 +1,11 @@
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'jekyll'
|
require 'jekyll'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'net/https'
|
require 'net/http'
|
||||||
require 'open-uri'
|
|
||||||
require 'uri'
|
require 'uri'
|
||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
# ruby -r './lib/jekyll/migrators/posterous.rb' -e 'Jekyll::Posterous.process(email, pass, api_token, blog, tags_key)'
|
# ruby -r './lib/jekyll/migrators/posterous.rb' -e 'Jekyll::Posterous.process(email, pass, api_key, blog)'
|
||||||
# You can find your api token in posterous api page - http://posterous.com/api . Click on any of the 'view token' links to see your token.
|
|
||||||
# blog is optional, by default it is the primary one
|
|
||||||
|
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module Posterous
|
module Posterous
|
||||||
|
@ -17,9 +14,6 @@ module Jekyll
|
||||||
raise ArgumentError, 'Stuck in a redirect loop. Please double check your email and password' if limit == 0
|
raise ArgumentError, 'Stuck in a redirect loop. Please double check your email and password' if limit == 0
|
||||||
|
|
||||||
response = nil
|
response = nil
|
||||||
|
|
||||||
puts uri_str
|
|
||||||
puts '-------'
|
|
||||||
Net::HTTP.start('posterous.com') do |http|
|
Net::HTTP.start('posterous.com') do |http|
|
||||||
req = Net::HTTP::Get.new(uri_str)
|
req = Net::HTTP::Get.new(uri_str)
|
||||||
req.basic_auth @email, @pass
|
req.basic_auth @email, @pass
|
||||||
|
@ -29,50 +23,36 @@ module Jekyll
|
||||||
case response
|
case response
|
||||||
when Net::HTTPSuccess then response
|
when Net::HTTPSuccess then response
|
||||||
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
|
when Net::HTTPRedirection then fetch(response['location'], limit - 1)
|
||||||
when Net::HTTPForbidden then
|
|
||||||
retry_after = response.to_hash['retry-after'][0]
|
|
||||||
puts "We have been told to try again after #{retry_after} seconds"
|
|
||||||
sleep(retry_after.to_i + 1)
|
|
||||||
fetch(uri_str, limit - 1)
|
|
||||||
else response.error!
|
else response.error!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.process(email, pass, api_token, blog = 'primary', tags_key = 'categories')
|
def self.process(email, pass, api_token, blog = 'primary')
|
||||||
@email, @pass, @api_token = email, pass, api_token
|
@email, @pass, @api_token = email, pass, api_token
|
||||||
FileUtils.mkdir_p "_posts"
|
FileUtils.mkdir_p "_posts"
|
||||||
|
|
||||||
posts = JSON.parse(self.fetch("/api/2/sites/#{blog}/posts?api_token=#{@api_token}").body)
|
posts = JSON.parse(self.fetch("/api/v2/users/me/sites/#{blog}/posts?api_token=#{@api_token}").body)
|
||||||
page = 1
|
page = 1
|
||||||
|
|
||||||
while posts.any?
|
while posts.any?
|
||||||
posts.each do |post|
|
posts.each do |post|
|
||||||
title = post["title"]
|
title = post["title"]
|
||||||
slug = title.gsub(/[^[:alnum:]]+/, '-').gsub(/^-+|-+$/, '').downcase
|
slug = title.gsub(/[^[:alnum:]]+/, '-').downcase
|
||||||
posterous_slug = post["slug"]
|
|
||||||
date = Date.parse(post["display_date"])
|
date = Date.parse(post["display_date"])
|
||||||
content = post["body_html"]
|
content = post["body_html"]
|
||||||
published = !post["is_private"]
|
published = !post["is_private"]
|
||||||
name = "%02d-%02d-%02d-%s.html" % [date.year, date.month, date.day, slug]
|
name = "%02d-%02d-%02d-%s.html" % [date.year, date.month, date.day, slug]
|
||||||
tags = []
|
|
||||||
post["tags"].each do |tag|
|
|
||||||
tags.push(tag["name"])
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the relevant fields as a hash, delete empty fields and convert
|
# Get the relevant fields as a hash, delete empty fields and convert
|
||||||
# to YAML for the header
|
# to YAML for the header
|
||||||
data = {
|
data = {
|
||||||
'layout' => 'post',
|
'layout' => 'post',
|
||||||
'title' => title.to_s,
|
'title' => title.to_s,
|
||||||
'published' => published,
|
'published' => published
|
||||||
tags_key => tags,
|
|
||||||
'posterous_url' => post["full_url"],
|
|
||||||
'posterous_slug' => posterous_slug
|
|
||||||
}.delete_if { |k,v| v.nil? || v == ''}.to_yaml
|
}.delete_if { |k,v| v.nil? || v == ''}.to_yaml
|
||||||
|
|
||||||
# Write out the data and content to file
|
# Write out the data and content to file
|
||||||
File.open("_posts/#{name}", "w") do |f|
|
File.open("_posts/#{name}", "w") do |f|
|
||||||
puts name
|
|
||||||
f.puts data
|
f.puts data
|
||||||
f.puts "---"
|
f.puts "---"
|
||||||
f.puts content
|
f.puts content
|
||||||
|
@ -80,7 +60,7 @@ module Jekyll
|
||||||
end
|
end
|
||||||
|
|
||||||
page += 1
|
page += 1
|
||||||
posts = JSON.parse(self.fetch("/api/2/sites/#{blog}/posts?api_token=#{@api_token}&page=#{page}").body)
|
posts = JSON.parse(self.fetch("/api/v2/users/me/sites/#{blog}/posts?api_token=#{@api_token}&page=#{page}").body)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue