docfu 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/bin/docfu +6 -0
- data/lib/docfu.rb +13 -1
- data/lib/docfu/application.rb +108 -0
- data/lib/docfu/files/config.yml +119 -0
- data/lib/docfu/outputs.rb +5 -0
- data/lib/docfu/outputs/base.rb +80 -0
- data/lib/docfu/outputs/ebook.rb +12 -0
- data/lib/docfu/outputs/html.rb +12 -0
- data/lib/docfu/outputs/pdf.rb +144 -0
- data/lib/docfu/skeleton.rb +77 -0
- data/lib/docfu/templates/README.md.erb +3 -0
- data/lib/docfu/templates/book.tex +153 -0
- data/lib/docfu/templates/info.yml.erb +7 -0
- metadata +37 -6
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -19,7 +19,7 @@ Jeweler::Tasks.new do |gem|
|
|
19
19
|
gem.name = "docfu"
|
20
20
|
gem.homepage = "http://github.com/seryl/docfu"
|
21
21
|
gem.license = "MIT"
|
22
|
-
gem.summary = %Q{
|
22
|
+
gem.summary = %Q{Docs like a ninja}
|
23
23
|
gem.description = %Q{Utility to simplify creating documentation/books/ebooks/html/etc. Based highly upon the ProGit setup.}
|
24
24
|
gem.email = "joshtoft@gmail.com"
|
25
25
|
gem.authors = ["Josh Toft"]
|
data/bin/docfu
ADDED
data/lib/docfu.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'docfu')
|
2
|
+
require 'erb'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
require 'mixlib/cli'
|
7
|
+
|
8
|
+
# Document like a ninja
|
1
9
|
module Docfu
|
2
|
-
VERSION = '0.0.
|
10
|
+
VERSION = '0.0.2'
|
3
11
|
end
|
12
|
+
|
13
|
+
require 'docfu/outputs'
|
14
|
+
require 'docfu/skeleton'
|
15
|
+
require 'docfu/application'
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# The commandline docfu application.
|
3
|
+
class Docfu::Application
|
4
|
+
include Mixlib::CLI
|
5
|
+
|
6
|
+
# Default aliases for running docfu commands.
|
7
|
+
DEFAULT_ALIASES = {
|
8
|
+
:create_new_project => ['new', 'create', 'n'],
|
9
|
+
:generate_output => ['generate', 'make', 'g']
|
10
|
+
}
|
11
|
+
|
12
|
+
banner """Example usage:
|
13
|
+
docfu new [document]
|
14
|
+
docfu generate
|
15
|
+
docfu generate [pdf,ebook,html]
|
16
|
+
"""
|
17
|
+
|
18
|
+
option :author,
|
19
|
+
:short => "-a AUTHOR",
|
20
|
+
:long => "--author AUTHOR",
|
21
|
+
:default => "author",
|
22
|
+
:description => "The author of the document"
|
23
|
+
|
24
|
+
option :exclude,
|
25
|
+
:short => "-e EXLCUDE",
|
26
|
+
:long => "--exclude EXCLUDE",
|
27
|
+
:default => 'figures,figures-dia,figures-source,README.md',
|
28
|
+
:description => "The list of files and directories to exclude from scripts"
|
29
|
+
|
30
|
+
option :title,
|
31
|
+
:short => "-t TITLE",
|
32
|
+
:long => "--title TITLE",
|
33
|
+
:default => "title",
|
34
|
+
:description => "The title of the document"
|
35
|
+
|
36
|
+
option :language,
|
37
|
+
:short => "-l LANGUAGE",
|
38
|
+
:long => "--language LANGUAGE",
|
39
|
+
:default => "en",
|
40
|
+
:description => "The languages to build - defaults to english [en]"
|
41
|
+
|
42
|
+
option :debug,
|
43
|
+
:short => "-d",
|
44
|
+
:long => "--debug",
|
45
|
+
:description => "Enable debugging",
|
46
|
+
:boolean => true,
|
47
|
+
:default => false
|
48
|
+
|
49
|
+
option :version,
|
50
|
+
:short => "-v",
|
51
|
+
:long => "--version",
|
52
|
+
:description => "Show docfu version",
|
53
|
+
:boolean => true,
|
54
|
+
:proc => lambda { |v| puts "docfu: #{::Docfu::VERSION}" },
|
55
|
+
:exit => 0
|
56
|
+
|
57
|
+
option :help,
|
58
|
+
:short => "-h",
|
59
|
+
:long => "--help",
|
60
|
+
:description => "Show this message",
|
61
|
+
:on => :tail,
|
62
|
+
:boolean => true,
|
63
|
+
:show_options => true,
|
64
|
+
:exit => 0
|
65
|
+
|
66
|
+
def run
|
67
|
+
trap("INT") { exit 0 }
|
68
|
+
parse_options
|
69
|
+
run_commands
|
70
|
+
end
|
71
|
+
|
72
|
+
def aliases(cmd)
|
73
|
+
DEFAULT_ALIASES.each { |k, v| return k if v.include?(cmd) }
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def run_commands
|
78
|
+
if ARGV.size == 0 || aliases(ARGV.first).nil?
|
79
|
+
puts self.opt_parser.help
|
80
|
+
exit 0
|
81
|
+
else
|
82
|
+
send(aliases(ARGV.first).to_sym)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_new_project
|
87
|
+
project_folder = (ARGV.size >= 2) ? ARGV.last : nil
|
88
|
+
puts "Creating new project #{project_folder}"
|
89
|
+
Docfu::Skeleton.setup_directory_structure(project_folder)
|
90
|
+
Docfu::Skeleton.write_config_yml(project_folder)
|
91
|
+
Docfu::Skeleton.write_info_yml(project_folder, config)
|
92
|
+
puts "Complete."
|
93
|
+
end
|
94
|
+
|
95
|
+
def generate_output
|
96
|
+
gen_type = (ARGV.size >= 2) ? ARGV.last : 'pdf'
|
97
|
+
invalid_type_error unless ['pdf', 'ebook', 'html'].include? gen_type
|
98
|
+
out = Docfu.const_get(gen_type.capitalize).new
|
99
|
+
out.check_missing_commands
|
100
|
+
out.check_valid_project
|
101
|
+
out.generate(config[:language].split(','), config[:debug])
|
102
|
+
end
|
103
|
+
|
104
|
+
def invalid_type_error
|
105
|
+
puts "Error: invalid type. Please use one of `pdf, ebook, html`."
|
106
|
+
exit 0
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
default:
|
2
|
+
font: Liberation Serif
|
3
|
+
bold: "{* Bold}"
|
4
|
+
mono: Liberation Mono
|
5
|
+
prechap: "Chapter "
|
6
|
+
postchap: ""
|
7
|
+
presect: "Section "
|
8
|
+
postsect: ""
|
9
|
+
dql: "“"
|
10
|
+
dqr: "”"
|
11
|
+
con: "Contents"
|
12
|
+
fig: "Figure "
|
13
|
+
tab: "Table "
|
14
|
+
indent: "\\qquad"
|
15
|
+
thanks: ""
|
16
|
+
zh:
|
17
|
+
langrule: "\\XeTeXlinebreakskip=0em plus 0.1em minus 0.01em\n\\XeTeXlinebreakpenalty=0"
|
18
|
+
font: AR PL UMing CN
|
19
|
+
bold: AR PL UKai CN
|
20
|
+
mono: AR PL UKai CN
|
21
|
+
prechap: "第"
|
22
|
+
postchap: "章"
|
23
|
+
presect: ""
|
24
|
+
postsect: "节"
|
25
|
+
con: "目录"
|
26
|
+
fig: "图 "
|
27
|
+
tab: "表 "
|
28
|
+
indent: "文"
|
29
|
+
zh-tw:
|
30
|
+
langrule: "\\XeTeXlinebreakskip=0em plus 0.1em minus 0.01em\n\\XeTeXlinebreakpenalty=0"
|
31
|
+
font: AR PL UMing TW
|
32
|
+
bold: AR PL UKai TW
|
33
|
+
mono: AR PL UKai TW
|
34
|
+
prechap: "第"
|
35
|
+
postchap: "章"
|
36
|
+
presect: ""
|
37
|
+
postsect: "節"
|
38
|
+
dql: "『"
|
39
|
+
dqr: "』"
|
40
|
+
con: "目錄"
|
41
|
+
fig: "圖 "
|
42
|
+
tab: "表 "
|
43
|
+
indent: "文"
|
44
|
+
ja:
|
45
|
+
langrule: "\\XeTeXlinebreakskip=0em plus 0.1em minus 0.01em\n\\XeTeXlinebreakpenalty=0"
|
46
|
+
# font: Japan
|
47
|
+
# font: Sazanami Mincho
|
48
|
+
font: IPAPMincho
|
49
|
+
bold: VL PGothic
|
50
|
+
# bold: Sazanami Gothic
|
51
|
+
# bold: IPAPGothic
|
52
|
+
mono: VL Gothic
|
53
|
+
prechap: "第"
|
54
|
+
postchap: "章"
|
55
|
+
presect: ""
|
56
|
+
postsect: "節"
|
57
|
+
dql: "『"
|
58
|
+
dqr: "』"
|
59
|
+
con: "目次"
|
60
|
+
fig: "図"
|
61
|
+
tab: "表"
|
62
|
+
indent: "あ"
|
63
|
+
ru:
|
64
|
+
prechap: "Глава "
|
65
|
+
presect: "Раздел "
|
66
|
+
con: "Содержание"
|
67
|
+
fig: "Рисунок "
|
68
|
+
tab: "Таблица "
|
69
|
+
dql: "«"
|
70
|
+
dqr: "»"
|
71
|
+
cs:
|
72
|
+
prechap: "Kapitola "
|
73
|
+
presect: "Oddíl "
|
74
|
+
dql: "„"
|
75
|
+
dqr: "“"
|
76
|
+
fig: "Obrázek "
|
77
|
+
tab: "Tabulka "
|
78
|
+
fr:
|
79
|
+
prechap: "Chapitre "
|
80
|
+
presect: "Section "
|
81
|
+
fig: "Figure "
|
82
|
+
tab: "Tableau "
|
83
|
+
font: Linux Libertine
|
84
|
+
mono: Courier New
|
85
|
+
con: "Table des matières"
|
86
|
+
langrule: "\\frenchspacing\\usepackage{fontspec}\n\\fontspec[Ligatures={Common}]{Linux Libertine}\n"
|
87
|
+
thanks: ""
|
88
|
+
dql: "«\\,"
|
89
|
+
dqr: "\\,»"
|
90
|
+
mk:
|
91
|
+
fig: "Слика"
|
92
|
+
con: "Содржина"
|
93
|
+
prechap: "Поглавје"
|
94
|
+
presect: "Секција"
|
95
|
+
dql: "„"
|
96
|
+
dqr: "“"
|
97
|
+
tab: "Табела"
|
98
|
+
de:
|
99
|
+
langrule: "\\frenchspacing"
|
100
|
+
dql: "„"
|
101
|
+
dqr: "“"
|
102
|
+
ko:
|
103
|
+
langrule: "\\XeTeXlinebreakskip=0em plus 0.1em minus 0.01em\n\\XeTeXlinebreakpenalty=0"
|
104
|
+
font: UnBatang
|
105
|
+
bold: UnGraphic
|
106
|
+
mono: UnDotum
|
107
|
+
prechap: ""
|
108
|
+
postchap: "장"
|
109
|
+
presect: ""
|
110
|
+
postsect: "절"
|
111
|
+
con: "목차"
|
112
|
+
fig: "그림"
|
113
|
+
tab: "표"
|
114
|
+
be:
|
115
|
+
prechap: "Глава "
|
116
|
+
presect: "Раздзел "
|
117
|
+
con: "Змест"
|
118
|
+
fig: "Малюнак "
|
119
|
+
tab: "Табліца "
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Docfu
|
3
|
+
class BaseOutput
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
def generate(languages, debug)
|
7
|
+
puts "This output class has not been implemented"
|
8
|
+
exit 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_commands
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_missing_commands
|
16
|
+
missing = required_commands.reject{|command| command_exists?(command)}
|
17
|
+
unless missing.empty?
|
18
|
+
puts "Missing dependencies: #{missing.join(', ')}."
|
19
|
+
puts "Install these and try again."
|
20
|
+
exit 0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def project_home
|
25
|
+
@home ||= Dir.pwd
|
26
|
+
end
|
27
|
+
|
28
|
+
def command_exists?(command)
|
29
|
+
if File.executable?(command) then
|
30
|
+
return command
|
31
|
+
end
|
32
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).map do |path|
|
33
|
+
cmd = "#{path}/#{command}"
|
34
|
+
File.executable?(cmd) \
|
35
|
+
|| File.executable?("#{cmd}.exe") \
|
36
|
+
|| File.executable?("#{cmd}.cmd")
|
37
|
+
end.inject{|a, b| a || b}
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_valid_project
|
41
|
+
not_a_project_error unless contains_info_yaml? and contains_config_yaml?
|
42
|
+
end
|
43
|
+
|
44
|
+
def contains_info_yaml?
|
45
|
+
File.exists? "#{project_home}/info.yml"
|
46
|
+
end
|
47
|
+
|
48
|
+
def contains_config_yaml?
|
49
|
+
File.exists? "#{project_home}/config.yml"
|
50
|
+
end
|
51
|
+
|
52
|
+
def info
|
53
|
+
@info ||= YAML::load(File.open("#{project_home}/info.yml"))
|
54
|
+
end
|
55
|
+
|
56
|
+
def config
|
57
|
+
@config ||= YAML::load(File.open("#{project_home}/config.yml"))
|
58
|
+
end
|
59
|
+
|
60
|
+
def not_a_project_error
|
61
|
+
puts "This directory doesn't appear to be docfu repository."
|
62
|
+
puts "To create a new docfu repository type: docfu new [document]"
|
63
|
+
exit 0
|
64
|
+
end
|
65
|
+
|
66
|
+
def figures(&block)
|
67
|
+
begin
|
68
|
+
Dir["#{project_home}/figures/18333*.png"].each do |file|
|
69
|
+
cp(file, file.sub(/18333fig0(\d)0?(\d+)\-tn/, '\1.\2'))
|
70
|
+
end
|
71
|
+
block.call
|
72
|
+
ensure
|
73
|
+
Dir["#{project_home}/figures/18333*.png"].each do |file|
|
74
|
+
rm(file.gsub(/18333fig0(\d)0?(\d+)\-tn/, '\1.\2'))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$:.unshift File.dirname(__FILE__)
|
3
|
+
require 'base'
|
4
|
+
|
5
|
+
module Docfu
|
6
|
+
class Pdf < BaseOutput
|
7
|
+
def generate(languages, debug)
|
8
|
+
figures do
|
9
|
+
languages.each do |lang|
|
10
|
+
cfg = config['default'].merge(config[lang]) rescue config['default']
|
11
|
+
template = ERB.new(IO.read(tex_template), 0, '<>')
|
12
|
+
|
13
|
+
puts "#{lang}:"
|
14
|
+
markdown = Dir["#{project_home}/#{lang}/*/*.md"].sort.map do |file|
|
15
|
+
File.read(file)
|
16
|
+
end.join("\n\n")
|
17
|
+
|
18
|
+
print " Parsing markdown... "
|
19
|
+
latex = IO.popen('pandoc -p --no-wrap -f markdown -t latex', 'w+') do |pipe|
|
20
|
+
pipe.write(pre_pandoc(markdown, cfg))
|
21
|
+
pipe.close_write
|
22
|
+
post_pandoc(pipe.read, cfg)
|
23
|
+
end
|
24
|
+
puts "done"
|
25
|
+
|
26
|
+
print " Creating main.tex for #{lang}... "
|
27
|
+
dir = "#{project_home}/#{lang}"
|
28
|
+
mkdir_p(dir)
|
29
|
+
File.open("#{dir}/main.tex", 'w') do |file|
|
30
|
+
file.write(template.result(binding))
|
31
|
+
end
|
32
|
+
puts "done"
|
33
|
+
|
34
|
+
abort = false
|
35
|
+
|
36
|
+
puts "Running XeTeX:"
|
37
|
+
cd(project_home)
|
38
|
+
3.times do |i|
|
39
|
+
print " Pass #{i + 1}... "
|
40
|
+
IO.popen("xelatex -output-directory=\"#{dir}\" \"#{dir}/main.tex\" 2>&1") do |pipe|
|
41
|
+
unless debug
|
42
|
+
if ~ /^!\s/
|
43
|
+
puts "failed with:\n #{$_.strip}"
|
44
|
+
puts " Consider running this again with --debug."
|
45
|
+
abort = true
|
46
|
+
end while pipe.gets and not abort
|
47
|
+
else
|
48
|
+
STDERR.print while pipe.gets rescue abort = true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
break if abort
|
52
|
+
puts "done"
|
53
|
+
end
|
54
|
+
|
55
|
+
unless abort
|
56
|
+
print " Moving output to #{info['title'].split(' ').join('_')}.#{lang}.pdf... "
|
57
|
+
mv("#{dir}/main.pdf", "#{project_home}/#{info['title'].split(' ').join('_')}.#{lang}.pdf")
|
58
|
+
puts "done"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def required_commands
|
65
|
+
['pandoc', 'xelatex']
|
66
|
+
end
|
67
|
+
|
68
|
+
def output_dir
|
69
|
+
"#{project_home}/pdf"
|
70
|
+
end
|
71
|
+
|
72
|
+
def tex_template
|
73
|
+
"#{Docfu::Skeleton.templates_location}/book.tex"
|
74
|
+
end
|
75
|
+
|
76
|
+
def replace(string, &block)
|
77
|
+
string.instance_eval do
|
78
|
+
alias :s :gsub!
|
79
|
+
instance_eval(&block)
|
80
|
+
end
|
81
|
+
string
|
82
|
+
end
|
83
|
+
|
84
|
+
def verbatim_sanitize(string)
|
85
|
+
string.gsub('\\', '{\textbackslash}').
|
86
|
+
gsub('~', '{\textasciitilde}').
|
87
|
+
gsub(/([\$\#\_\^\%])/, '\\\\' + '\1{}')
|
88
|
+
end
|
89
|
+
|
90
|
+
def pre_pandoc(string, cfg)
|
91
|
+
replace(string) do
|
92
|
+
# Pandoc discards #### subsubsections #### - this hack recovers them
|
93
|
+
s(/\#\#\#\# (.*?) \#\#\#\#/, 'SUBSUBSECTION: \1')
|
94
|
+
|
95
|
+
# Turns URLs into clickable links
|
96
|
+
s(/\`(http:\/\/[A-Za-z0-9\/\%\&\=\-\_\\\.]+)\`/, '<\1>')
|
97
|
+
s(/(\n\n)\t(http:\/\/[A-Za-z0-9\/\%\&\=\-\_\\\.]+)\n([^\t]|\t\n)/, '\1<\2>\1')
|
98
|
+
|
99
|
+
# Process figures
|
100
|
+
s(/Insert\s18333fig\d+\.png\s*\n.*?\d{1,2}-\d{1,2}\. (.*)/, 'FIG: \1')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def post_pandoc(string, cfg)
|
105
|
+
replace(string) do
|
106
|
+
space = /\s/
|
107
|
+
|
108
|
+
# Reformat for the book documentclass as opposed to article
|
109
|
+
s('\section', '\chap')
|
110
|
+
s('\sub', '\\')
|
111
|
+
s(/SUBSUBSECTION: (.*)/, '\subsubsection{\1}')
|
112
|
+
|
113
|
+
# Enable proper cross-reference
|
114
|
+
s(/#{cfg['fig'].gsub(space, '\s')}\s*(\d+)\-\-(\d+)/, '\imgref{\1.\2}')
|
115
|
+
s(/#{cfg['tab'].gsub(space, '\s')}\s*(\d+)\-\-(\d+)/, '\tabref{\1.\2}')
|
116
|
+
s(/#{cfg['prechap'].gsub(space, '\s')}\s*(\d+)(\s*)#{cfg['postchap'].gsub(space, '\s')}/, '\chapref{\1}\2')
|
117
|
+
|
118
|
+
# Miscellaneous fixes
|
119
|
+
s(/FIG: (.*)/, '\img{\1}')
|
120
|
+
s('\begin{enumerate}[1.]', '\begin{enumerate}')
|
121
|
+
s(/(\w)--(\w)/, '\1-\2')
|
122
|
+
s(/``(.*?)''/, "#{cfg['dql']}\\1#{cfg['dqr']}")
|
123
|
+
|
124
|
+
# Typeset the maths in the book with TeX
|
125
|
+
s('\verb!p = (n(n-1)/2) * (1/2^160))!', '$p = \frac{n(n-1)}{2} \times \frac{1}{2^{160}}$)')
|
126
|
+
s('2\^{}80', '$2^{80}$')
|
127
|
+
s(/\sx\s10\\\^\{\}(\d+)/, '\e{\1}')
|
128
|
+
|
129
|
+
# Convert inline-verbatims into \texttt (which is able to wrap)
|
130
|
+
s(/\\verb(\W)(.*?)\1/) do
|
131
|
+
"{\\texttt{#{verbatim_sanitize($2)}}}"
|
132
|
+
end
|
133
|
+
|
134
|
+
# Ensure monospaced stuff is in a smaller font
|
135
|
+
s(/(\\verb(\W).*?\2)/, '{\footnotesize\1}')
|
136
|
+
s(/(\\begin\{verbatim\}.*?\\end\{verbatim\})/m, '{\footnotesize\1}')
|
137
|
+
|
138
|
+
# Shaded verbatim block
|
139
|
+
s(/(\\begin\{verbatim\}.*?\\end\{verbatim\})/m, '\begin{shaded}\1\end{shaded}')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Docfu::Skeleton
|
3
|
+
class << self
|
4
|
+
# Sets up a new directory structure for a document project.
|
5
|
+
#
|
6
|
+
# @param [ String ] folder The project path.
|
7
|
+
def setup_directory_structure(folder)
|
8
|
+
Dir.mkdir(folder) unless Dir.exists? folder
|
9
|
+
%w( figures figures-dia figures-source en ).each do |fold|
|
10
|
+
Dir.mkdir("#{folder}/#{fold}") unless Dir.exists? "#{folder}/#{fold}"
|
11
|
+
end
|
12
|
+
setup_readme(folder)
|
13
|
+
end
|
14
|
+
|
15
|
+
# The location of the files folder.
|
16
|
+
def files_location
|
17
|
+
File.join(File.expand_path(File.dirname(__FILE__)), 'files')
|
18
|
+
end
|
19
|
+
|
20
|
+
# The location of the templates folder.
|
21
|
+
def templates_location
|
22
|
+
File.join(File.expand_path(File.dirname(__FILE__)), 'templates')
|
23
|
+
end
|
24
|
+
|
25
|
+
# Sets up the README for the project.
|
26
|
+
#
|
27
|
+
# @param [ String ] project The name of the new project.
|
28
|
+
def setup_readme(project)
|
29
|
+
readme_erb_file = "#{templates_location}/README.md.erb"
|
30
|
+
readme_template = ERB.new(IO.read(readme_erb_file), 0, '<>')
|
31
|
+
unless File.exists? "#{project}/README.md"
|
32
|
+
File.open("#{project}/README.md", 'w') { |f|
|
33
|
+
f.write(readme_template.result(binding))
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Writes the config.yml if it's missing for the current project,
|
39
|
+
# otherwise it returns early.
|
40
|
+
def write_config_yml(project)
|
41
|
+
config_file = "#{project}/config.yml"
|
42
|
+
unless File.exists? config_file
|
43
|
+
puts "Creating config.yml..."
|
44
|
+
cfg = File.open("#{files_location}/config.yml", 'r').read
|
45
|
+
File.open(config_file, 'w') { |f| f.write(cfg) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Takes an info hash and converts it into it's yaml equivalent config.yml.
|
50
|
+
#
|
51
|
+
# @param [ Hash ] config The config hash to convert into the config.yml.
|
52
|
+
#
|
53
|
+
# @return [ String ] The configuration yml in string format.
|
54
|
+
def generate_info_yml(config)
|
55
|
+
sane_config = config.inject({}) {|res, (k,v)| res[k.to_s] = v; res }
|
56
|
+
sane_config['author'] ||= 'author'
|
57
|
+
sane_config['title'] ||= 'title'
|
58
|
+
sane_config['exclude'] = sane_config['exclude'].split(",")
|
59
|
+
info_erb_file = "#{templates_location}/info.yml.erb"
|
60
|
+
info_template = ERB.new(IO.read(info_erb_file), 0, '<>')
|
61
|
+
info_template.result(binding)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Writes the info.yml if it's missing for the current project,
|
65
|
+
# otherwise it returns early.
|
66
|
+
#
|
67
|
+
# @param [ Hash ] info The info hash to pass.
|
68
|
+
def write_info_yml(project, info)
|
69
|
+
unless File.exists? "#{project}/info.yml"
|
70
|
+
puts "Creating info.yml..."
|
71
|
+
inf = generate_info_yml(info)
|
72
|
+
File.open("#{project}/info.yml", 'w') { |f| f.write(inf) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
\documentclass[a4paper]{book}
|
2
|
+
\usepackage[
|
3
|
+
%urlbordercolor = {1 1 1},
|
4
|
+
%linkbordercolor = {1 1 1},
|
5
|
+
%citebordercolor = {1 1 1},
|
6
|
+
urlcolor = blue,
|
7
|
+
colorlinks = true,
|
8
|
+
citecolor = black,
|
9
|
+
linkcolor = black]{hyperref}
|
10
|
+
\usepackage{graphicx}
|
11
|
+
\usepackage{xltxtra}
|
12
|
+
\usepackage{fancyhdr}
|
13
|
+
\usepackage{booktabs}
|
14
|
+
\usepackage{indentfirst}
|
15
|
+
\usepackage{framed,color}
|
16
|
+
\usepackage{array}
|
17
|
+
\usepackage[font=small,format=plain,labelfont=bf,up,textfont=it,up]{caption}
|
18
|
+
|
19
|
+
\definecolor{shadecolor}{gray}{0.90}
|
20
|
+
|
21
|
+
\setromanfont[Mapping=tex-text,BoldFont=<%= cfg['bold'] %>]{<%= cfg['font'] %>}
|
22
|
+
\setmonofont{<%= cfg['mono'] %>}
|
23
|
+
|
24
|
+
\XeTeXlinebreaklocale{<%= lang %>}
|
25
|
+
<%= cfg['langrule'] %>
|
26
|
+
|
27
|
+
\settowidth{\parindent}{<%= cfg['indent'] %>}
|
28
|
+
|
29
|
+
\title{<%= info['title'] %>}
|
30
|
+
\author{<%= info['author'] %>}
|
31
|
+
|
32
|
+
\makeatletter
|
33
|
+
\let\savedauthor=\@author
|
34
|
+
\let\savedtitle=\@title
|
35
|
+
\def\imgwidth{.6\linewidth}
|
36
|
+
\def\maxwidth{\ifdim\Gin@nat@width>\imgwidth\imgwidth
|
37
|
+
\else\Gin@nat@width\fi}
|
38
|
+
\makeatother
|
39
|
+
|
40
|
+
\title{\textbf{\savedtitle}}
|
41
|
+
\author{\textbf{\savedauthor}\thanks{<%= cfg['thanks'] %>}}
|
42
|
+
\def\w3cdtfymd{\the\year-\ifnum\month<10 0\fi\the\month-\ifnum\day<10 0\fi\the\day}
|
43
|
+
\date{\w3cdtfymd}
|
44
|
+
\renewcommand{\thefootnote}{\fnsymbol{footnote}}
|
45
|
+
|
46
|
+
\newcommand{\PreserveBackslash}[1]{\let\temp=\\#1\let\\=\temp}
|
47
|
+
\let\PBS=\PreserveBackslash
|
48
|
+
\makeatletter
|
49
|
+
\setlength\headheight{12\p@}
|
50
|
+
\setlength\headsep {.25in}
|
51
|
+
\setlength\topskip {10\p@}
|
52
|
+
\setlength\footskip{.35in}
|
53
|
+
\setlength\textwidth{400\p@}
|
54
|
+
|
55
|
+
\setlength\@tempdima{\paperheight}
|
56
|
+
\addtolength\@tempdima{-2in}
|
57
|
+
\divide\@tempdima\baselineskip
|
58
|
+
\@tempcnta=\@tempdima
|
59
|
+
\setlength\textheight{\@tempcnta\baselineskip}
|
60
|
+
\addtolength\textheight{\topskip}
|
61
|
+
|
62
|
+
\setlength\@tempdima {\paperwidth}
|
63
|
+
\addtolength\@tempdima {-\textwidth}
|
64
|
+
\setlength\oddsidemargin {\paperwidth}
|
65
|
+
\addtolength\oddsidemargin {-2.35in}
|
66
|
+
\addtolength\oddsidemargin {-\textwidth}
|
67
|
+
\setlength\marginparwidth {0pt}
|
68
|
+
\@settopoint\oddsidemargin
|
69
|
+
\@settopoint\marginparwidth
|
70
|
+
\setlength\evensidemargin {\paperwidth}
|
71
|
+
\addtolength\evensidemargin{-2.35in}
|
72
|
+
\addtolength\evensidemargin{-\textwidth}
|
73
|
+
\@settopoint\evensidemargin
|
74
|
+
|
75
|
+
\setlength\topmargin{\paperheight}
|
76
|
+
\addtolength\topmargin{-2in}
|
77
|
+
\addtolength\topmargin{-\headheight}
|
78
|
+
\addtolength\topmargin{-\headsep}
|
79
|
+
\addtolength\topmargin{-\textheight}
|
80
|
+
\addtolength\topmargin{-\footskip} % this might be wrong!
|
81
|
+
\addtolength\topmargin{-.5\topmargin}
|
82
|
+
\@settopoint\topmargin
|
83
|
+
\makeatother
|
84
|
+
|
85
|
+
\fancypagestyle{plain}{\fancyhf{}\fancyfoot[LE,RO]{\footnotesize\textbf\thepage}}
|
86
|
+
\pagestyle{plain}
|
87
|
+
|
88
|
+
\renewcommand{\headrulewidth}{0pt}
|
89
|
+
\renewcommand{\footrulewidth}{0pt}
|
90
|
+
|
91
|
+
\newcounter{img}[chapter]
|
92
|
+
\renewcommand{\theimg}{\thechapter.\arabic{img}}
|
93
|
+
\newcommand{\img}[1]{\begin{figure}[h!]
|
94
|
+
\refstepcounter{img}
|
95
|
+
\label{img:\theimg}
|
96
|
+
\centering\includegraphics[width=\maxwidth]{figures/\theimg.png}
|
97
|
+
\caption{#1}
|
98
|
+
\end{figure}}
|
99
|
+
|
100
|
+
\newcounter{tab}[chapter]
|
101
|
+
\renewcommand{\thetab}{\thechapter.\arabic{tab}}
|
102
|
+
|
103
|
+
\newcommand{\prechap}{<%= cfg['prechap'] %>}
|
104
|
+
\newcommand{\postchap}{<%= cfg['postchap'] %>}
|
105
|
+
\newcommand{\presect}{<%= cfg['presect'] %>}
|
106
|
+
\newcommand{\postsect}{<%= cfg['postsect'] %>}
|
107
|
+
\renewcommand{\chaptermark}[1]{\markboth{\textbf{\prechap \thechapter \postchap}\hspace*{1ex}#1}{}}
|
108
|
+
\renewcommand{\sectionmark}[1]{\markright{\textbf{\presect \thesection \postsect}\hspace*{1ex}#1}}
|
109
|
+
\newcommand{\chap}[1]{\newpage\thispagestyle{empty}\chapter{#1}\label{chap:\thechapter}}
|
110
|
+
\newcommand{\chapref}[1]{\hyperref[chap:#1]{\prechap #1\postchap}}
|
111
|
+
\newcommand{\imgref}[1]{\hyperref[img:#1]{<%= cfg['fig'] %>#1}}
|
112
|
+
\newcommand{\tabref}[1]{\hyperref[tab:#1]{<%= cfg['tab'] %>#1}}
|
113
|
+
\newcommand{\e}[1]{$ \times 10^{#1}$}
|
114
|
+
\renewcommand{\contentsname}{<%= cfg['con'] %>}
|
115
|
+
\renewcommand{\figurename}{<%= cfg['fig'] %>}
|
116
|
+
\renewcommand{\tablename}{<%= cfg['tab'] %>}
|
117
|
+
|
118
|
+
\makeatletter
|
119
|
+
\def\@makechapterhead#1{%
|
120
|
+
\vspace*{50\p@}%
|
121
|
+
{\parindent \z@ \raggedright \normalfont
|
122
|
+
\ifnum \c@secnumdepth >\m@ne
|
123
|
+
\if@mainmatter
|
124
|
+
\huge\bfseries \prechap \thechapter \postchap
|
125
|
+
\par\nobreak
|
126
|
+
\vskip 20\p@
|
127
|
+
\fi
|
128
|
+
\fi
|
129
|
+
\interlinepenalty\@M
|
130
|
+
\Huge \bfseries #1\par\nobreak
|
131
|
+
\vskip 40\p@
|
132
|
+
}}
|
133
|
+
\makeatother
|
134
|
+
|
135
|
+
\linespread{1.3}
|
136
|
+
|
137
|
+
\begin{document}
|
138
|
+
\frontmatter
|
139
|
+
\maketitle
|
140
|
+
\thispagestyle{empty}
|
141
|
+
\setcounter{tocdepth}{4}
|
142
|
+
\tableofcontents\newpage\thispagestyle{empty}
|
143
|
+
|
144
|
+
\mainmatter
|
145
|
+
\fancyhf{}
|
146
|
+
\fancyhead[LE]{{\small\leftmark}}
|
147
|
+
\fancyhead[RO]{{\small\rightmark}}
|
148
|
+
\fancyhead[RE,LO]{{\small\savedauthor\hspace*{1ex}\textbf{\savedtitle}}}
|
149
|
+
\fancyfoot[LE,RO]{\small\textbf\thepage}
|
150
|
+
\pagestyle{fancy}
|
151
|
+
|
152
|
+
<%= latex %>
|
153
|
+
\end{document}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docfu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mixlib-cli
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.2.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.2
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rspec
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,7 +126,8 @@ dependencies:
|
|
110
126
|
description: Utility to simplify creating documentation/books/ebooks/html/etc. Based
|
111
127
|
highly upon the ProGit setup.
|
112
128
|
email: joshtoft@gmail.com
|
113
|
-
executables:
|
129
|
+
executables:
|
130
|
+
- docfu
|
114
131
|
extensions: []
|
115
132
|
extra_rdoc_files:
|
116
133
|
- LICENSE.txt
|
@@ -122,10 +139,22 @@ files:
|
|
122
139
|
- LICENSE.txt
|
123
140
|
- README.md
|
124
141
|
- Rakefile
|
142
|
+
- bin/docfu
|
125
143
|
- features/docfu.feature
|
126
144
|
- features/step_definitions/docfu_steps.rb
|
127
145
|
- features/support/env.rb
|
128
146
|
- lib/docfu.rb
|
147
|
+
- lib/docfu/application.rb
|
148
|
+
- lib/docfu/files/config.yml
|
149
|
+
- lib/docfu/outputs.rb
|
150
|
+
- lib/docfu/outputs/base.rb
|
151
|
+
- lib/docfu/outputs/ebook.rb
|
152
|
+
- lib/docfu/outputs/html.rb
|
153
|
+
- lib/docfu/outputs/pdf.rb
|
154
|
+
- lib/docfu/skeleton.rb
|
155
|
+
- lib/docfu/templates/README.md.erb
|
156
|
+
- lib/docfu/templates/book.tex
|
157
|
+
- lib/docfu/templates/info.yml.erb
|
129
158
|
- spec/docfu_spec.rb
|
130
159
|
- spec/spec_helper.rb
|
131
160
|
homepage: http://github.com/seryl/docfu
|
@@ -141,6 +170,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
170
|
- - ! '>='
|
142
171
|
- !ruby/object:Gem::Version
|
143
172
|
version: '0'
|
173
|
+
segments:
|
174
|
+
- 0
|
175
|
+
hash: 2011303864533425458
|
144
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
177
|
none: false
|
146
178
|
requirements:
|
@@ -149,9 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
181
|
version: '0'
|
150
182
|
requirements: []
|
151
183
|
rubyforge_project:
|
152
|
-
rubygems_version: 1.8.
|
184
|
+
rubygems_version: 1.8.24
|
153
185
|
signing_key:
|
154
186
|
specification_version: 3
|
155
|
-
summary:
|
187
|
+
summary: Docs like a ninja
|
156
188
|
test_files: []
|
157
|
-
has_rdoc:
|