Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

big restructure, start of tests

  • Loading branch information...
commit d8d2b329460e8109f3e3dde0d41bfc8357ea5cd5 1 parent 0a86dc5
@schacon schacon authored
View
34 Rakefile
@@ -0,0 +1,34 @@
+def command?(command)
+ system("type #{command} > /dev/null 2>&1")
+end
+
+#
+# Tests
+#
+
+task :default => :test
+
+desc "Run the test suite"
+task :test do
+ rg = command?(:rg)
+ Dir['test/**/*_test.rb'].each do |f|
+ rg ? sh("rg #{f}") : ruby(f)
+ end
+end
+
+
+#
+# Publishing
+#
+
+desc "Push a new version to Gemcutter"
+task :publish do
+ require 'git-scribe/version'
+
+ sh "gem build git-scribe.gemspec"
+ sh "gem push git-scribe-#{GitScribe::Version}.gem"
+ sh "git tag v#{GitScribe::Version}"
+ sh "git push origin v#{GitScribe::Version}"
+ sh "git push origin master"
+end
+
View
3  bin/git-scribe
@@ -2,5 +2,6 @@
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'git-scribe'
+require 'git-scribe/cli'
-GitScribe.start
+GitScribe.new.run
View
334 lib/git-scribe.rb
@@ -1,175 +1,38 @@
require 'rubygems'
require 'nokogiri'
require 'liquid'
-require 'subcommand'
+
+require 'git-scribe/generate'
+require 'git-scribe/check'
+require 'git-scribe/init'
require 'fileutils'
require 'pp'
class GitScribe
- include Subcommands
+ include Init
+ include Check
+ include Generate
+
+ attr_accessor :subcommand, :args, :options
BOOK_FILE = 'book.asc'
OUTPUT_TYPES = ['pdf', 'epub', 'mobi', 'html', 'site']
SCRIBE_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
def initialize
-
+ @subcommand = nil
+ @args = []
@options = {}
- global_options do |opts|
- opts.banner = "Usage: #{$0} [options] [subcommand [options]]"
- opts.description = "git-scribe helps you write books with the power of Git"
- opts.separator ""
- opts.separator "Global options are:"
- opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
- @options[:verbose] = v
- end
- end
-
- command :init do |opts|
- opts.banner = "Usage: git scribe init (directory)"
- opts.description = "initialize a new book layout"
- opts.on("-l", "--lang", "choose a default language (en)") do |v|
- @options[:lang] = lang || 'en'
- end
- end
-
- command :gen do |opts|
- opts.banner = "Usage: git scribe gen [options]"
- opts.description = "generate digital formats"
- end
-
- @command = opt_parse
- end
-
- def self.start
- GitScribe.new.run
- end
-
- def run
- if @command && self.respond_to?(@command)
- self.send @command
- else
- help
- end
end
## COMMANDS ##
-
def die(message)
raise message
end
- # start a new scribe directory with skeleton structure
- def init
- name = ARGV.shift
- die("needs a directory name") if !name
- die("directory already exists") if File.exists?(name)
-
- puts "inititalizing #{name}"
- from_stdir = File.join(SCRIBE_ROOT, 'template')
- FileUtils.cp_r from_stdir, name
- end
-
- # check that we have everything needed
- def check
- # check for asciidoc
- if !check_can_run('asciidoc')
- puts "asciidoc is not present, please install it for anything to work"
- else
- puts "asciidoc - ok"
- end
-
- # check for xsltproc
- if !check_can_run('xsltproc --version')
- puts "xsltproc is not present, please install it for html generation"
- else
- puts "xsltproc - ok"
- end
-
- # check for a2x - should be installed with asciidoc, but you never know
- if !check_can_run('a2x')
- puts "a2x is not present, please install it for epub generation"
- else
- puts "a2x - ok"
- end
-
- # check for fop
- if !check_can_run('fop -version')
- puts "fop is not present, please install for PDF generation"
- else
- puts "fop - ok"
- end
- end
-
- def check_can_run(command)
- `#{command} 2>&1`
- $?.exitstatus == 0
- end
- # generate the new media
- def gen
- type = ARGV.shift || 'all'
- prepare_output_dir
-
- gather_and_process
-
- types = type == 'all' ? OUTPUT_TYPES : [type]
-
- output = []
- Dir.chdir("output") do
- types.each do |out_type|
- call = 'do_' + out_type
- if self.respond_to? call
- self.send call
- else
- puts "NOT A THING: #{call}"
- end
- end
- # clean up
- `rm #{BOOK_FILE}`
- end
- end
-
- def prepare_output_dir
- Dir.mkdir('output') rescue nil
- Dir.chdir('output') do
- Dir.mkdir('stylesheets') rescue nil
- puts SCRIBE_ROOT
- from_stdir = File.join(SCRIBE_ROOT, 'stylesheets')
- pp from_stdir
- FileUtils.cp_r from_stdir, '.'
- end
- end
-
- def a2x(type)
- "a2x -f #{type} -d book "
- end
-
- def a2x_wss(type)
- a2x(type) + " --stylesheet=stylesheets/handbookish.css"
- end
-
- def do_pdf
- puts "GENERATING PDF"
- # TODO: syntax highlighting (fop?)
- puts `asciidoc -b docbook #{BOOK_FILE}`
- strparams = {'callout.graphics' => 0,
- 'navig.graphics' => 0,
- 'admon.textlabel' => 1,
- 'admon.graphics' => 0}
- param = strparams.map { |k, v| "--stringparam #{k} #{v}" }.join(' ')
- puts cmd = "xsltproc --nonet #{param} --output #{local('book.fo')} #{base('docbook-xsl/fo.xsl')} #{local('book.xml')}"
- puts `#{cmd}`
- cmd = "fop -fo #{local('book.fo')} -pdf #{local('book.pdf')}"
- puts `#{cmd}`
- #puts `#{a2x('pdf')} -v --fop #{BOOK_FILE}`
- if $?.exitstatus == 0
- 'book.pdf'
- end
- end
-
def local(file)
File.expand_path(File.join(Dir.pwd, file))
end
@@ -178,178 +41,19 @@ def base(file)
File.join(SCRIBE_ROOT, file)
end
- def do_epub
- puts "GENERATING EPUB"
- # TODO: look for custom stylesheets
- `#{a2x_wss('epub')} -v #{BOOK_FILE}`
- puts 'exit status', $?.exitstatus
- 'book.epub'
- end
-
- def do_html
- puts "GENERATING HTML"
- # TODO: look for custom stylesheets
- #puts `#{a2x_wss('xhtml')} -v #{BOOK_FILE}`
- styledir = local('stylesheets')
- puts cmd = "asciidoc -a stylesdir=#{styledir} -a theme=handbookish #{BOOK_FILE}"
- `#{cmd}`
- puts 'exit status', $?.exitstatus
- 'book.html'
- end
-
- def do_site
- puts "GENERATING SITE"
- # TODO: check if html was already done
- puts `asciidoc -b docbook #{BOOK_FILE}`
- xsldir = base('docbook-xsl/xhtml')
- `xsltproc --stringparam html.stylesheet stylesheets/handbookish.css --nonet #{xsldir}/chunk.xsl book.xml`
-
- source = File.read('index.html')
- html = Nokogiri::HTML.parse(source, nil, 'utf-8')
-
- sections = []
- c = -1
-
- # each chapter
- html.css('.toc > dl').each do |section|
- section.children.each do |item|
- if item.name == 'dt' # section
- c += 1
- sections[c] ||= {'number' => c}
- link = item.css('a').first
- sections[c]['title'] = title = link.text
- sections[c]['href'] = href = link['href']
- clean_title = title.downcase.gsub(/[^a-z0-9\-_]+/, '_') + '.html'
- sections[c]['link'] = clean_title
- if href[0, 10] == 'index.html'
- sections[c]['link'] = 'title.html'
- end
- sections[c]['sub'] = []
- end
- if item.name == 'dd' # subsection
- item.css('dt').each do |sub|
- link = sub.css('a').first
- data = {}
- data['title'] = title = link.text
- data['href'] = href = link['href']
- data['link'] = sections[c]['link'] + '#' + href.split('#').last
- sections[c]['sub'] << data
- end
- end
- end
- puts
- end
-
- pp sections
-
- book_title = html.css('head > title').text
- content = html.css('body > div')[1]
- content.css('.toc').first.remove
- content = content.inner_html
-
- puts content
- sections.each do |s|
- content.gsub!(s['href'], s['link'])
- end
-
- template_dir = File.join(SCRIBE_ROOT, 'site', 'default')
-
- # copy the template files in
- files = Dir.glob(template_dir + '/*')
- FileUtils.cp_r files, '.'
-
- Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_dir)
- index_template = Liquid::Template.parse(File.read(File.join(template_dir, 'index.html')))
- page_template = Liquid::Template.parse(File.read(File.join(template_dir, 'page.html')))
-
- # write the index page
- main_data = {
- 'book_title' => book_title,
- 'sections' => sections
- }
- File.open('index.html', 'w+') do |f|
- f.puts index_template.render( main_data )
- end
-
- # write the title page
- File.open('title.html', 'w+') do |f|
- data = {
- 'title' => sections.first['title'],
- 'sub' => sections.first['sub'],
- 'prev' => {'link' => 'index.html', 'title' => "Main"},
- 'home' => {'link' => 'index.html', 'title' => "Home"},
- 'next' => sections[1],
- 'content' => content
- }
- data.merge!(main_data)
- f.puts page_template.render( data )
- end
-
- # write the other pages
- sections.each_with_index do |section, i|
-
- if i > 0 # skip title page
- source = File.read(section['href'])
- html = Nokogiri::HTML.parse(source, nil, 'utf-8')
-
- content = html.css('body > div')[1].to_html
- sections.each do |s|
- content.gsub!(s['href'], s['link'])
- end
-
- File.open(section['link'], 'w+') do |f|
- next_section = nil
- if i <= sections.size
- next_section = sections[i+1]
- end
- data = {
- 'title' => section['title'],
- 'sub' => section['sub'],
- 'prev' => sections[i-1],
- 'home' => {'link' => 'index.html', 'title' => "Home"},
- 'next' => next_section,
- 'content' => content
- }
- data.merge!(main_data)
- f.puts page_template.render( data )
- end
- #File.unlink(section['href'])
-
- puts i
- puts section['title']
- puts section['href']
- puts section['link']
- puts
- end
-
- #File.unlink
- end
- end
-
-
- # create a new file by concatenating all the ones we find
- def gather_and_process
- files = Dir.glob("book/*")
- FileUtils.cp_r files, 'output'
- end
-
- # DISPLAY HELPER FUNCTIONS #
+ # API/DATA HELPER FUNCTIONS #
- def l(info, size)
- clean(info)[0, size].ljust(size)
+ def git(subcommand)
+ `git #{subcommand}`.chomp
end
- def r(info, size)
- clean(info)[0, size].rjust(size)
+ def first_arg(args)
+ Array(args).shift
end
- def clean(info)
- info.to_s.gsub("\n", ' ')
+ # eventually we'll want to log this or have it retrievable elsehow
+ def info(message)
+ puts message
end
- # API/DATA HELPER FUNCTIONS #
-
- def git(command)
- `git #{command}`.chomp
- end
end
View
39 lib/git-scribe/check.rb
@@ -0,0 +1,39 @@
+class GitScribe
+ module Check
+ # check that we have everything needed
+ def check
+ # check for asciidoc
+ if !check_can_run('asciidoc')
+ puts "asciidoc is not present, please install it for anything to work"
+ else
+ puts "asciidoc - ok"
+ end
+
+ # check for xsltproc
+ if !check_can_run('xsltproc --version')
+ puts "xsltproc is not present, please install it for html generation"
+ else
+ puts "xsltproc - ok"
+ end
+
+ # check for a2x - should be installed with asciidoc, but you never know
+ if !check_can_run('a2x')
+ puts "a2x is not present, please install it for epub generation"
+ else
+ puts "a2x - ok"
+ end
+
+ # check for fop
+ if !check_can_run('fop -version')
+ puts "fop is not present, please install for PDF generation"
+ else
+ puts "fop - ok"
+ end
+ end
+
+ def check_can_run(command)
+ `#{command} 2>&1`
+ $?.exitstatus == 0
+ end
+ end
+end
View
79 lib/git-scribe/cli.rb
@@ -0,0 +1,79 @@
+require 'subcommand'
+
+class GitScribe
+ include Subcommands
+
+ def info(message)
+ puts message
+ end
+
+ module CLI
+
+ def run
+ parse_options
+ if @subcommand && self.respond_to?(@subcommand)
+ begin
+ self.send @subcommand, @args
+ rescue Object => e
+ error e
+ end
+ else
+ help
+ end
+ end
+
+ def error(e)
+ puts 'Error: ' + e.to_s
+ end
+
+ def help
+ puts print_actions
+ end
+
+ def parse_options
+ @options = {}
+ global_options do |opts|
+ opts.banner = "Usage: #{$0} [options] [subcommand [options]]"
+ opts.description = "git-scribe helps you write books with the power of Git"
+ opts.separator ""
+ opts.separator "Global options are:"
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
+ @options[:verbose] = v
+ end
+ end
+
+ command :init do |opts|
+ opts.banner = "Usage: git scribe init (directory)"
+ opts.description = "initialize a new book layout"
+ opts.on("-l", "--lang", "choose a default language (en)") do |v|
+ @options[:lang] = lang || 'en'
+ end
+ end
+
+ command :gen do |opts|
+ opts.banner = "Usage: git scribe gen [options]"
+ opts.description = "generate digital formats"
+ end
+
+ @subcommand = opt_parse
+ @args = ARGV
+ end
+
+ # DISPLAY HELPER FUNCTIONS #
+
+ def l(info, size)
+ clean(info)[0, size].ljust(size)
+ end
+
+ def r(info, size)
+ clean(info)[0, size].rjust(size)
+ end
+
+ def clean(info)
+ info.to_s.gsub("\n", ' ')
+ end
+
+ end
+
+ include CLI
+end
View
220 lib/git-scribe/generate.rb
@@ -0,0 +1,220 @@
+class GitScribe
+ module Generate
+ # generate the new media
+ def gen(args = [])
+ type = first_arg(args) || 'all'
+ prepare_output_dir
+
+ gather_and_process
+
+ types = type == 'all' ? OUTPUT_TYPES : [type]
+
+ output = []
+ Dir.chdir("output") do
+ types.each do |out_type|
+ call = 'do_' + out_type
+ if self.respond_to? call
+ self.send call
+ else
+ puts "NOT A THING: #{call}"
+ end
+ end
+ # clean up
+ `rm #{BOOK_FILE}`
+ end
+ end
+
+ def prepare_output_dir
+ Dir.mkdir('output') rescue nil
+ Dir.chdir('output') do
+ Dir.mkdir('stylesheets') rescue nil
+ puts SCRIBE_ROOT
+ from_stdir = File.join(SCRIBE_ROOT, 'stylesheets')
+ pp from_stdir
+ FileUtils.cp_r from_stdir, '.'
+ end
+ end
+
+ def a2x(type)
+ "a2x -f #{type} -d book "
+ end
+
+ def a2x_wss(type)
+ a2x(type) + " --stylesheet=stylesheets/handbookish.css"
+ end
+
+ def do_pdf
+ puts "GENERATING PDF"
+ # TODO: syntax highlighting (fop?)
+ puts `asciidoc -b docbook #{BOOK_FILE}`
+ strparams = {'callout.graphics' => 0,
+ 'navig.graphics' => 0,
+ 'admon.textlabel' => 1,
+ 'admon.graphics' => 0}
+ param = strparams.map { |k, v| "--stringparam #{k} #{v}" }.join(' ')
+ puts cmd = "xsltproc --nonet #{param} --output #{local('book.fo')} #{base('docbook-xsl/fo.xsl')} #{local('book.xml')}"
+ puts `#{cmd}`
+ cmd = "fop -fo #{local('book.fo')} -pdf #{local('book.pdf')}"
+ puts `#{cmd}`
+ #puts `#{a2x('pdf')} -v --fop #{BOOK_FILE}`
+ if $?.exitstatus == 0
+ 'book.pdf'
+ end
+ end
+
+ def do_epub
+ puts "GENERATING EPUB"
+ # TODO: look for custom stylesheets
+ `#{a2x_wss('epub')} -v #{BOOK_FILE}`
+ puts 'exit status', $?.exitstatus
+ 'book.epub'
+ end
+
+ def do_html
+ puts "GENERATING HTML"
+ # TODO: look for custom stylesheets
+ #puts `#{a2x_wss('xhtml')} -v #{BOOK_FILE}`
+ styledir = local('stylesheets')
+ puts cmd = "asciidoc -a stylesdir=#{styledir} -a theme=handbookish #{BOOK_FILE}"
+ `#{cmd}`
+ puts 'exit status', $?.exitstatus
+ 'book.html'
+ end
+
+ def do_site
+ puts "GENERATING SITE"
+ # TODO: check if html was already done
+ puts `asciidoc -b docbook #{BOOK_FILE}`
+ xsldir = base('docbook-xsl/xhtml')
+ `xsltproc --stringparam html.stylesheet stylesheets/handbookish.css --nonet #{xsldir}/chunk.xsl book.xml`
+
+ source = File.read('index.html')
+ html = Nokogiri::HTML.parse(source, nil, 'utf-8')
+
+ sections = []
+ c = -1
+
+ # each chapter
+ html.css('.toc > dl').each do |section|
+ section.children.each do |item|
+ if item.name == 'dt' # section
+ c += 1
+ sections[c] ||= {'number' => c}
+ link = item.css('a').first
+ sections[c]['title'] = title = link.text
+ sections[c]['href'] = href = link['href']
+ clean_title = title.downcase.gsub(/[^a-z0-9\-_]+/, '_') + '.html'
+ sections[c]['link'] = clean_title
+ if href[0, 10] == 'index.html'
+ sections[c]['link'] = 'title.html'
+ end
+ sections[c]['sub'] = []
+ end
+ if item.name == 'dd' # subsection
+ item.css('dt').each do |sub|
+ link = sub.css('a').first
+ data = {}
+ data['title'] = title = link.text
+ data['href'] = href = link['href']
+ data['link'] = sections[c]['link'] + '#' + href.split('#').last
+ sections[c]['sub'] << data
+ end
+ end
+ end
+ puts
+ end
+
+ pp sections
+
+ book_title = html.css('head > title').text
+ content = html.css('body > div')[1]
+ content.css('.toc').first.remove
+ content = content.inner_html
+
+ puts content
+ sections.each do |s|
+ content.gsub!(s['href'], s['link'])
+ end
+
+ template_dir = File.join(SCRIBE_ROOT, 'site', 'default')
+
+ # copy the template files in
+ files = Dir.glob(template_dir + '/*')
+ FileUtils.cp_r files, '.'
+
+ Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_dir)
+ index_template = Liquid::Template.parse(File.read(File.join(template_dir, 'index.html')))
+ page_template = Liquid::Template.parse(File.read(File.join(template_dir, 'page.html')))
+
+ # write the index page
+ main_data = {
+ 'book_title' => book_title,
+ 'sections' => sections
+ }
+ File.open('index.html', 'w+') do |f|
+ f.puts index_template.render( main_data )
+ end
+
+ # write the title page
+ File.open('title.html', 'w+') do |f|
+ data = {
+ 'title' => sections.first['title'],
+ 'sub' => sections.first['sub'],
+ 'prev' => {'link' => 'index.html', 'title' => "Main"},
+ 'home' => {'link' => 'index.html', 'title' => "Home"},
+ 'next' => sections[1],
+ 'content' => content
+ }
+ data.merge!(main_data)
+ f.puts page_template.render( data )
+ end
+
+ # write the other pages
+ sections.each_with_index do |section, i|
+
+ if i > 0 # skip title page
+ source = File.read(section['href'])
+ html = Nokogiri::HTML.parse(source, nil, 'utf-8')
+
+ content = html.css('body > div')[1].to_html
+ sections.each do |s|
+ content.gsub!(s['href'], s['link'])
+ end
+
+ File.open(section['link'], 'w+') do |f|
+ next_section = nil
+ if i <= sections.size
+ next_section = sections[i+1]
+ end
+ data = {
+ 'title' => section['title'],
+ 'sub' => section['sub'],
+ 'prev' => sections[i-1],
+ 'home' => {'link' => 'index.html', 'title' => "Home"},
+ 'next' => next_section,
+ 'content' => content
+ }
+ data.merge!(main_data)
+ f.puts page_template.render( data )
+ end
+ #File.unlink(section['href'])
+
+ puts i
+ puts section['title']
+ puts section['href']
+ puts section['link']
+ puts
+ end
+
+ #File.unlink
+ end
+ end
+
+ # create a new file by concatenating all the ones we find
+ def gather_and_process
+ files = Dir.glob("book/*")
+ FileUtils.cp_r files, 'output'
+ end
+
+ end
+end
View
14 lib/git-scribe/init.rb
@@ -0,0 +1,14 @@
+class GitScribe
+ module Init
+ # start a new scribe directory with skeleton structure
+ def init(args = [])
+ name = first_arg(args)
+ die("needs a directory name") if !name
+ die("directory already exists") if File.exists?(name)
+
+ info "inititalizing #{name}"
+ from_stdir = File.join(SCRIBE_ROOT, 'template')
+ FileUtils.cp_r from_stdir, name
+ end
+ end
+end
View
3  lib/git-scribe/version.rb
@@ -0,0 +1,3 @@
+class GitScribe
+ VERSION = '0.0.5'
+end
View
15 test/init_test.rb
@@ -0,0 +1,15 @@
+require File.expand_path "../test_helper", __FILE__
+
+context "scribe init tests" do
+ setup do
+ @scribe = GitScribe.new
+ end
+
+ test "can't init a scribe repo without a directory" do
+ in_temp_dir do
+ assert_raise RuntimeError do
+ @scribe.init
+ end
+ end
+ end
+end
View
44 test/test_helper.rb
@@ -0,0 +1,44 @@
+dir = File.dirname(File.expand_path(__FILE__))
+$LOAD_PATH.unshift dir + '/../lib'
+$TESTING = true
+
+require 'test/unit'
+require 'rubygems'
+require 'git-scribe'
+require 'pp'
+require 'tempfile'
+
+begin
+ require 'leftright'
+rescue LoadError
+end
+
+##
+# test/spec/mini 3
+# http://gist.github.com/25455
+# chris@ozmm.org
+#
+def context(*args, &block)
+ return super unless (name = args.first) && block
+ require 'test/unit'
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
+ def self.test(name, &block)
+ define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
+ end
+ def self.xtest(*args) end
+ def self.setup(&block) define_method(:setup, &block) end
+ def self.teardown(&block) define_method(:teardown, &block) end
+ end
+ (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
+ klass.class_eval &block
+end
+
+def in_temp_dir
+ f = Tempfile.new('test')
+ p = f.path
+ f.unlink
+ Dir.mkdir(p)
+ Dir.chdir(p) do
+ yield
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.