Last active
August 29, 2015 14:27
-
-
Save hainuo/1d9c65d44e831b493e53 to your computer and use it in GitHub Desktop.
ruby 将markdown 转换为epub mobi pdf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# Simple script to generate EPUB book (which could be also converted | |
# to MOBI then) from site sources | |
# | |
# It depends on on 'eeepub' ruby gem and also you should have | |
# ebook-convert executable somewhere in path (or use --path argument | |
# for that) | |
# | |
# Usage is simple: | |
# | |
# gem install eeepub | |
# ./script/publish | |
require 'eeepub' | |
require 'date' | |
require 'fileutils' | |
require 'optparse' | |
calibre_path = '/Applications/calibre.app/Contents/MacOS' | |
OptionParser.new do |opts| | |
opts.banner = "Usage: #{ARGV[0]} [options]" | |
opts.on("-p", "--calibre-path PATH", "The path to ebook-convert binary, it also look in PATH env (default: #{calibre_path})") do |v| | |
calibre_path = v | |
end | |
opts.on_tail("-?", "--help", "Show this message") do | |
puts opts | |
exit | |
end | |
end.parse! | |
ENV["PATH"] = "#{ENV["PATH"]}:#{calibre_path}" | |
def executable?(bin) | |
ENV["PATH"].split(":").any? do |path| | |
File.executable?(File.join(path, bin)) | |
end | |
end | |
unless executable?("ebook-convert") | |
abort("ebook-convert not found in PATH. Use --calibre-path option to specify custom path") | |
end | |
today = Date.today | |
system("jekyll build") | |
GUIDE_DIR = File.expand_path("../..", __FILE__) | |
ORIGINAL_DIR = "#{GUIDE_DIR}/_site" | |
TEMP_DIR = "epub_tmp" | |
EBOOK_DIR = File.join GUIDE_DIR, "ebooks" | |
FileUtils.mkdir_p("#{TEMP_DIR}/images") | |
FileUtils.cp(Dir["#{ORIGINAL_DIR}/images/*"], "#{TEMP_DIR}/images") | |
FileUtils.mkdir_p("#{TEMP_DIR}/css") | |
FileUtils.cp("#{ORIGINAL_DIR}/css/styles.css", "#{TEMP_DIR}/css") | |
File.open("#{TEMP_DIR}/css/styles.css", "a+") do |f| | |
f.puts <<-EOS.gsub(/^\s*/, "") | |
/* epub patch */ | |
body {width:100%;} | |
p {width:100%;} | |
EOS | |
end | |
Dir["#{ORIGINAL_DIR}/*.html"].each do |f| | |
old = File.read(f) | |
new = old.gsub(%r("/css/styles.css"), %q("css/styles.css")) | |
File.write("#{TEMP_DIR}/#{File.basename(f)}", new) | |
end | |
navigation = [ | |
{:label => "Preface", :content => "preface.html"}, | |
{:label => "Introduction", :content => "intro.html"}, | |
{:label => "Part 1: Objects", :content => "minimum.html#chapter", :nav => [ | |
{:label => "Chapter 1: A Minimal Introduction to Ruby", :content => "minimum.html"}, | |
{:label => "Chapter 2: Objects", :content => "object.html"}, | |
{:label => "Chapter 3: Names and name tables", :content => "name.html"}, | |
{:label => "Chapter 4: Classes and modules", :content => "class.html"}, | |
{:label => "Chapter 5: Garbage collection", :content => "gc.html"}, | |
{:label => "Chapter 6: Variables and constants", :content => "variable.html"}, | |
{:label => "Chapter 7: Security", :content => "security.html"} | |
]}, | |
{:label => "Part 2: Syntax analysis", :content => "spec.html#chapter", :nav => [ | |
{:label => "Chapter 8: Ruby Language Details", :content => "spec.html"}, | |
{:label => "Chapter 9: yacc crash course", :content => "yacc.html"}, | |
{:label => "Chapter 10: Parser", :content => "parser.html"}, | |
{:label => "Chapter 11: Finite-state scanner", :content => "contextual.html"}, | |
{:label => "Chapter 12: Syntax tree construction", :content => "syntree.html"} | |
]}, | |
{:label => "Part 3: Evaluation", :content => "evaluator.html#chapter", :nav => [ | |
{:label => "Chapter 13: Structure of the evaluator", :content => "evaluator.html"}, | |
{:label => "Chapter 14: Context", :content => "module.html"}, | |
{:label => "Chapter 15: Methods", :content => "method.html"}, | |
{:label => "Chapter 16: Blocks", :content => "iterator.html"}, | |
{:label => "Chapter 17: Dynamic evaluation", :content => "anyeval.html"} | |
]}, | |
{:label => "Part 4: Around the evaluator", :content => "load.html#chapter", :nav => [ | |
{:label => "Chapter 18: Loading", :content => "load.html"}, | |
{:label => "Chapter 19: Threads", :content => "thread.html"} | |
]}, | |
{:label => "Final chapter: Ruby's future", :content => "fin.html"} | |
] | |
file_list = Dir["#{TEMP_DIR}/images/*"].map{|f| {f => "images"}} | |
file_list.push("#{TEMP_DIR}/css/styles.css" => "css") | |
def scan_navigation(nav, acc) | |
nav.each do |n| | |
if n[:content] && n[:content] !~ /#.*$/ | |
acc.push("#{TEMP_DIR}/#{n[:content]}") | |
end | |
if n[:nav] | |
scan_navigation(n[:nav], acc) | |
end | |
end | |
end | |
scan_navigation(navigation, file_list) | |
epub = EeePub.make do | |
title 'Ruby Hacking Guide' | |
creator 'Minero AOKI, Vincent ISAMBART, Clifford Escobar CAOILE' | |
rights 'The original work is Copyright © 2002 - 2004 Minero AOKI. Translated by Vincent ISAMBART and Clifford Escobar CAOILE This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike2.5 License' | |
date today | |
identifier 'http://ruby-hacking-guide.github.io/', :scheme => 'URL', :id => 'ruby-hacking-guide.github.io' | |
cover "images/book_cover.jpg" | |
files file_list | |
nav navigation | |
end | |
# because the source files are using HTML5 and epub prefer XML, we | |
# call initial output as dirty and rely on calibre to sanitize and | |
# build well-formed outputs | |
STDERR.print("write dirty EPUB ...") | |
FileUtils.mkdir_p EBOOK_DIR | |
sha = `git rev-parse HEAD`[0..5] | |
base_path = "#{EBOOK_DIR}/rhg-#{today}_#{sha}" | |
epub.save("#{base_path}-dirty.epub") | |
FileUtils.rm_rf("#{TEMP_DIR}") | |
STDERR.puts(" ok") | |
# now pass dirty file to calibre to produce PDF, MOBI and EPUB | |
STDERR.puts("RECONVERT EPUB ...") | |
system("ebook-convert #{base_path}-dirty.epub #{base_path}.epub") | |
STDERR.puts("RECONVERT EPUB ... ok") | |
STDERR.print("CONVERT TO MOBI ...") | |
system("ebook-convert #{base_path}-dirty.epub #{base_path}.pdf") | |
STDERR.puts("CONVERT TO MOBI ... ok") | |
STDERR.print("CONVERT TO PDF ...") | |
system("ebook-convert #{base_path}-dirty.epub #{base_path}.mobi") | |
STDERR.puts("CONVERT TO PDF ... ok") | |
STDERR.print("remove dirty EPUB ...") | |
FileUtils.rm_rf("#{base_path}-dirty.epub") | |
STDERR.puts(" ok") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment