mkbok 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/mkbok +268 -11
  2. data/lib/mkbok_version.rb +1 -1
  3. metadata +1 -1
data/bin/mkbok CHANGED
@@ -1,17 +1,274 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- puts "It is coming.."
3
+ require 'optparse'
4
+ require 'fileutils'
5
+ require 'erb'
6
+ require 'yaml'
4
7
 
5
- puts <<eof
6
- $ gem install mkbok
7
- $ mkbok create sample --title "learn mkbok"
8
- $ mkbok build --local # needs pandoc,XeTex packages
8
+ include FileUtils
9
9
 
10
- If you already follow the mkbok configuration, then
10
+ options = {}
11
+ CONFIG_FILE = File.join('.mkbok.yml')
12
+ if File.exists? CONFIG_FILE
13
+ config_options = YAML.load_file(CONFIG_FILE)
14
+ options.merge!(config_options)
15
+ end
16
+
17
+ option_parser = OptionParser.new do |opts|
18
+ executable_name = File.basename($PROGRAM_NAME)
19
+ opts.banner = "make ebooks from markdown plain text
20
+ Usage: #{executable_name} [options]
21
+ "
22
+ # Create a switch
23
+ opts.on("-b","--build FORMAT","build") do |format|
24
+ unless format=="pdf"
25
+ raise ArgumentError,"FORMAT must be in 'pdf' format"
26
+ end
27
+ options[:build] = format
28
+ end
29
+ # Create a flag
30
+ opts.on("-l","--lang LANG","language selection") do |lang|
31
+ unless lang=="zh" or lang=="en"
32
+ raise ArgumentError,"LANG must be in zh or en"
33
+ end
34
+ options[:lang] = lang
35
+ end
36
+ opts.on("-c","--config CONFIG","config file") do |config|
37
+ unless File.exists? config
38
+ raise ArgumentError,"config file \"#{config}\" doesn't exist"
39
+ end
40
+ options[:config] = config
41
+ end
42
+ opts.on("-t","--template template.tex","latex template file") do |template|
43
+ unless File.exists? template
44
+ raise ArgumentError,"template file \"#{template}\" doesn't exist"
45
+ end
46
+ options[:template] = template
47
+ end
48
+ opts.on("-n","--name book name","book name") do |name|
49
+ unless name =~ /^[a-zA-Z0-9]+$/
50
+ raise ArgumentError,"name should be [a-zA-Z0-9]"
51
+ end
52
+ options[:name] = name
53
+ end
54
+ end
55
+
56
+ option_parser.parse!
57
+ puts options.inspect
58
+
59
+ $here = File.expand_path(File.dirname(__FILE__))
60
+ $root = File.join($here)
61
+ $outDir = File.join($root, 'pdf')
62
+
63
+ def figures(&block)
64
+ begin
65
+ Dir["#$root/figures/18333*.png"].each do |file|
66
+ cp(file, file.sub(/18333fig0(\d)0?(\d+)\-tn/, '\1.\2'))
67
+ end
68
+ block.call
69
+ ensure
70
+ Dir["#$root/figures/18333*.png"].each do |file|
71
+ rm(file.gsub(/18333fig0(\d)0?(\d+)\-tn/, '\1.\2'))
72
+ end
73
+ end
74
+ end
75
+
76
+ def command_exists?(command)
77
+ if File.executable?(command) then
78
+ return command
79
+ end
80
+ ENV['PATH'].split(File::PATH_SEPARATOR).map do |path|
81
+ cmd = "#{path}/#{command}"
82
+ File.executable?(cmd) || File.executable?("#{cmd}.exe") || File.executable?("#{cmd}.cmd")
83
+ end.inject{|a, b| a || b}
84
+ end
85
+
86
+ def replace(string, &block)
87
+ string.instance_eval do
88
+ alias :s :gsub!
89
+ instance_eval(&block)
90
+ end
91
+ string
92
+ end
93
+
94
+ def verbatim_sanitize(string)
95
+ string.gsub('\\', '{\textbackslash}').
96
+ gsub('~', '{\textasciitilde}').
97
+ gsub(/([\$\#\_\^\%])/, '\\\\' + '\1{}')
98
+ end
99
+
100
+ def pre_pandoc(string, config)
101
+ replace(string) do
102
+ s /\#\#\#\#\# (.*?) \#\#\#\#\#/, 'PARASECTION: \1'
103
+ # Pandoc discards #### subsubsections #### - this hack recovers them
104
+ s /\#\#\#\# (.*?) \#\#\#\#/, 'SUBSUBSECTION: \1'
105
+
106
+ # Turns URLs into clickable links
107
+ s /\`(http:\/\/[A-Za-z0-9\/\%\&\=\-\_\\\.]+)\`/, '<\1>'
108
+ s /(\n\n)\t(http:\/\/[A-Za-z0-9\/\%\&\=\-\_\\\.]+)\n([^\t]|\t\n)/, '\1<\2>\1'
109
+
110
+ # Process figures
111
+ s /Insert\s18333fig\d+\.png\s*\n.*?\d{1,2}-\d{1,2}\. (.*)/, 'FIG: \1'
112
+ end
113
+ end
114
+
115
+ def post_pandoc(string, config, lang, chapter=true)
116
+ replace(string) do
117
+ space = /\s/
118
+
119
+ # Reformat for the book documentclass as opposed to article
120
+ s '\section', '\chap'
121
+ s '\sub', '\\'
122
+ s /SUBSUBSECTION: (.*)/, '\subsubsection{\1}'
123
+ s /PARASECTION: (.*)/, '\paragraph{\1}'
124
+
125
+ # Enable proper cross-reference
126
+ s /#{config['fig'].gsub(space, '\s')}\s*(\d+)\-\-(\d+)/, '\imgref{\1.\2}'
127
+ s /#{config['tab'].gsub(space, '\s')}\s*(\d+)\-\-(\d+)/, '\tabref{\1.\2}'
128
+ s /#{config['prechap'].gsub(space, '\s')}\s*(\d+)(\s*)#{config['postchap'].gsub(space, '\s')}/, '\chapref{\1}\2'
129
+
130
+ # Miscellaneous fixes
131
+ s /FIG: (.*)/, '\img{\1}'
132
+ s '\begin{enumerate}[1.]', '\begin{enumerate}'
133
+ s /(\w)--(\w)/, '\1-\2'
134
+ s /``(.*?)''/, "#{config['dql']}\\1#{config['dqr']}"
135
+
136
+ # Typeset the maths in the book with TeX
137
+ s '\verb!p = (n(n-1)/2) * (1/2^160))!', '$p = \frac{n(n-1)}{2} \times \frac{1}{2^{160}}$)'
138
+ s '2\^{}80', '$2^{80}$'
139
+ s /\sx\s10\\\^\{\}(\d+)/, '\e{\1}'
140
+
141
+ # Convert inline-verbatims into \texttt (which is able to wrap)
142
+ s /\\verb(\W)(.*?)\1/ do
143
+ "{\\texttt{#{verbatim_sanitize($2)}}}"
144
+ end
145
+
146
+ # Ensure monospaced stuff is in a smaller font
147
+ s /(\\verb(\W).*?\2)/, '{\footnotesize\1}'
148
+ s /(\\begin\{verbatim\}.*?\\end\{verbatim\})/m, '{\footnotesize\1}'
149
+
150
+ # Shaded verbatim block
151
+ s /(\\begin\{verbatim\}.*?\\end\{verbatim\})/m, '\begin{shaded}\1\end{shaded}'
152
+
153
+ if lang=="zh"
154
+ # http://www.devdaily.com/blog/post/latex/control-line-spacing-in-itemize-enumerate-tags
155
+ # http://wiki.ctex.org/index.php/LaTeX/%E5%88%97%E8%A1%A8
156
+ # set the space of itemsize
157
+ s /(\\begin\{itemize\})/m,'\begin{itemize}\setlength{\itemsep}{1pt}\setlength{\parskip}{0pt}\setlength{\parsep}{0pt}'
158
+ s /(\\begin\{enumerate\})/m,'\begin{enumerate}\setlength{\itemsep}{1pt}\setlength{\parskip}{0pt}\setlength{\parsep}{0pt}'
159
+ # hardcode for itemize to use * instead of dot, which is missed in some chinese fonts
160
+ # and keep \item inside \enumerate env is not changed
161
+ # \item -> \item[*]
162
+ # solution is provided by Alexis, and it works under ruby 1.9+ only due to bug in 1.8.7
163
+ # http://stackoverflow.com/questions/9115018/regular-expression-using-ruby-string-gsub-method-to-replace-multi-matches
164
+ if RUBY_VERSION >= "1.9"
165
+ s /^\\item(?=((?!\\begin\{itemize\}).)*\\end\{itemize\})/m, '\\item[*]'
166
+ else
167
+ s /(^\\item)/m,'\item[*]'
168
+ end
169
+ end
170
+
171
+ if chapter != true
172
+ s /^\\chap\{(.*)\}/,'\chapter*{\1}'"\n"'\addcontentsline{toc}{chapter}{\1}'
173
+ s /^\\section\{(.*)\}/,'\section*{\1}'
174
+ s /^\\subsection\{(.*)\}/,'\subsection*{\1}'
175
+ end
176
+
177
+ end
178
+ end
179
+
180
+ #`
181
+
182
+ $config = YAML.load_file(options[:config])
183
+ template = ERB.new(File.read(options[:template]))
184
+ languages = [options[:lang]]
185
+ missing = ['pandoc', 'xelatex'].reject{|command| command_exists?(command)}
186
+ unless missing.empty?
187
+ puts "Missing dependencies: #{missing.join(', ')}."
188
+ puts "Install these and try again."
189
+ exit
190
+ end
191
+
192
+ figures do
193
+ languages.each do |lang|
194
+ config = $config['default'].merge($config[lang]) rescue $config['default']
195
+
196
+ puts "#{lang}:"
197
+ prefacemarkdown = Dir["#$root/#{lang}/0preface/*.markdown"].sort.map do |file|
198
+ File.read(file)
199
+ end.join("\n\n")
200
+
201
+ print "\tParsing preface markdown... "
202
+ preface = IO.popen('pandoc -p --no-wrap -f markdown -t latex', 'w+') do |pipe|
203
+ pipe.write(pre_pandoc(prefacemarkdown, config))
204
+ pipe.close_write
205
+ post_pandoc(pipe.read, config, lang, false)
206
+ end
207
+
208
+ chaptersmarkdown = Dir["#$root/#{lang}/*chapters/*.markdown"].sort.map do |file|
209
+ File.read(file)
210
+ end.join("\n\n")
211
+ puts "done"
212
+
213
+ print "\tParsing main chapters markdown... "
214
+ chapters = IO.popen('pandoc -p --no-wrap -f markdown -t latex', 'w+') do |pipe|
215
+ pipe.write(pre_pandoc(chaptersmarkdown, config))
216
+ pipe.close_write
217
+ post_pandoc(pipe.read, config, lang)
218
+ end
219
+ puts "done"
220
+
221
+ appendixmarkdown = Dir["#$root/#{lang}/*appendix/*.markdown"].sort.map do |file|
222
+ File.read(file)
223
+ end.join("\n\n")
224
+
225
+ print "\tParsing appendix markdown... "
226
+ appendix = IO.popen('pandoc -p --no-wrap -f markdown -t latex', 'w+') do |pipe|
227
+ pipe.write(pre_pandoc(appendixmarkdown, config))
228
+ pipe.close_write
229
+ post_pandoc(pipe.read, config, lang)
230
+ end
231
+ puts "done"
232
+
233
+ print "\tCreating main.tex for #{lang}... "
234
+ dir = "#$here/#{lang}"
235
+ mkdir_p(dir)
236
+
237
+ File.open("#{dir}/main.tex", 'w') do |file|
238
+ file.write(template.result(binding))
239
+ end
240
+ puts "done"
241
+
242
+ abort = false
243
+
244
+ puts "\tRunning XeTeX:"
245
+ cd($root)
246
+ 3.times do |i|
247
+ print "\t\tPass #{i + 1}... "
248
+ IO.popen("xelatex -output-directory=\"#{dir}\" \"#{dir}/main.tex\" 2>&1",'r:UTF-16LE:UTF-8') do |pipe|
249
+ unless $DEBUG
250
+ if ~ /^!\s/
251
+ puts "failed with:\n\t\t\t#{$_.strip}"
252
+ puts "\tConsider running this again with --debug."
253
+ abort = true
254
+ end while pipe.gets and not abort
255
+ else
256
+ STDERR.print while pipe.gets rescue abort = true
257
+ end
258
+ end
259
+ break if abort
260
+ puts "done"
261
+ end
262
+
263
+ unless abort
264
+ print "\tMoving output to #{name}.#{lang}.pdf... "
265
+ mv("#{dir}/main.pdf", "#$root/#{name}.#{lang}.pdf")
266
+ puts "done"
267
+ else
268
+ print "\tConvert error, exit !\n"
269
+ exit 1
270
+ end
271
+ end
272
+ end
11
273
 
12
- $ mkbok init # add needed configuration for your existing markdown files
13
- $ mkbok build --web http://mkbok.com/diy # it will zip file and upload to web
14
- $ mkbok build --web http://mkbok.com/ --source http://github.com/larrycai/mkbok # generate pdf from github
15
- eof
16
274
 
17
- puts "Please wait and check github.com/larrycai/mkbok"
data/lib/mkbok_version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module MkBok
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mkbok
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: