docfu 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|