mkbok 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.
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: