class Docfu::Pdf
Public Instance Methods
create_output_dir()
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 75 def create_output_dir FileUtils.mkdir_p(output_dir) end
generate(languages, debug)
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 6 def generate(languages, debug) create_output_dir unless File.exists? output_dir figures do languages.each do |lang| cfg = config['default'].merge(config[lang]) rescue config['default'] template = ERB.new(IO.read(tex_template), 0, '<>') puts "#{lang}:" markdown = Dir["#{project_home}/#{lang}/*/*.md"].sort.map do |file| File.read(file) end.join("\n\n") print " Parsing markdown... " latex = IO.popen('pandoc -p --no-wrap -f markdown -t latex', 'w+') do |pipe| pipe.write(pre_pandoc(markdown, cfg)) pipe.close_write post_pandoc(pipe.read, cfg) end puts "done" print " Creating main.tex for #{lang}... " dir = "#{project_home}/#{lang}" mkdir_p(dir) File.open("#{dir}/main.tex", 'w') do |file| file.write(template.result(binding)) end puts "done" abort = false puts "Running XeTeX:" cd(project_home) 3.times do |i| print " Pass #{i + 1}... " IO.popen("xelatex -output-directory=\"#{output_dir}\" \"#{dir}/main.tex\" 2>&1") do |pipe| unless debug if ~ /^!\s/ puts "failed with:\n #{$_.strip}" puts " Consider running this again with --debug." abort = true end while pipe.gets and not abort else STDERR.print while pipe.gets rescue abort = true end end break if abort puts "done" end unless abort print " Moving output to #{info['title'].split(' ').join('_')}.#{lang}.pdf... " ["aux", "log", "out", "toc"].each { |f| rm "#{output_dir}/main.#{f}" } mv("#{project_home}/main.pdf", "#{output_dir}/#{info['title'].split(' ').join('_')}.#{lang}.pdf") puts "done" end File.delete("#{dir}/main.tex") end end end
output_dir()
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 71 def output_dir "#{project_home}/pdf" end
post_pandoc(string, cfg)
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 128 def post_pandoc(string, cfg) replace(string) do space = /\s/ # Reformat for the book documentclass as opposed to article s('\section', '\chap') s('\sub', '\\') s(/SUBSUBSECTION: (.*)/, '\subsubsection{\1}') # Enable proper cross-reference s(/#{cfg['fig'].gsub(space, '\s')}\s*(\d+)\-\-(\d+)/, '\imgref{\1.\2}') s(/#{cfg['tab'].gsub(space, '\s')}\s*(\d+)\-\-(\d+)/, '\tabref{\1.\2}') s(/#{cfg['prechap'].gsub(space, '\s')}\s*(\d+)(\s*)#{cfg['postchap'].gsub(space, '\s')}/, '\chapref{\1}\2') # Miscellaneous fixes s(/FIG: (.*)/, '\img{\1}') s('\begin{enumerate}[1.]', '\begin{enumerate}') s(/(\w)--(\w)/, '\1-\2') s(/``(.*?)''/, "#{cfg['dql']}\\1#{cfg['dqr']}") # Typeset the maths in the book with TeX s('\verb!p = (n(n-1)/2) * (1/2^160))!', '$p = \frac{n(n-1)}{2} \times \frac{1}{2^{160}}$)') s('2\^{}80', '$2^{80}$') s(/\sx\s10\\\^\{\}(\d+)/, '\e{\1}') # Convert inline-verbatims into \texttt (which is able to wrap) s(/\\verb(\W)(.*?)\1/ ,'\\texttt{\2}') # s(/\\verb(\W)(.*?)\1/) do # "{\\texttt{#{verbatim_sanitize($2)}}}" # end # Style Tables s(/ctable\[pos = H, center, botcap\]\{..\}/ , 'ctable[pos = ht!, caption = ~ ,width = 130mm, center, botcap]{lX}') # Shaded verbatim block s(/(\\begin\{verbatim\}.*?\\end\{verbatim\})/m, '\begin{shaded}\1\end{shaded}') # Ensure monospaced stuff is in a smaller font # s(/(\\verb(\W).*?\2)/, '{\footnotesize\1}') # s(/(\\begin\{verbatim\}.*?\\end\{verbatim\})/m, '{\footnotesize\1}') end end
pre_pandoc(string, cfg)
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 97 def pre_pandoc(string, cfg) replace(string) do # Pandoc discards #### subsubsections #### - this hack recovers them s(/\#\#\#\#\# (.*?) \#\#\#\#\#/, 'PARAGRAPH: \1') s(/\#\#\#\# (.*?) \#\#\#\#/, 'SUBSUBSECTION: \1') # Turns URLs into clickable links s(/\`(http:\/\/[A-Za-z0-9\/\%\&\=\-\_\\\.\(\)\#]+)\`/, '<\1>') s(/(\n\n)\t(http:\/\/[A-Za-z0-9\/\%\&\=\-\_\\\.\(\)\#]+)\n([^\t]|\t\n)/, '\1<\2>\1') # Match table in markdown and change them to pandoc's markdown tables s(/(\n(\n\t([^\t\n]+)\t([^\t\n]+))+\n\n)/) do first_col=20 t = $1.gsub(/(\n?)\n\t([^\t\n]+)\t([^\t\n]+)/) do if $1=="\n" # This is the header, need to add the dash line $1 << "\n " << $2 << " "*(first_col-$2.length) << $3 << "\n " << "-"*18 << " " << "-"*$3.length else # Table row : format the first column as typewriter and align $1 << "\n `" << $2 << "`" + " "*(first_col-$2.length-2) << $3 end end t << "\n" end # Process figures s(/Insert\s18333fig\d+\.png\s*\n.*?\d{1,2}-\d{1,2}\. (.*)/, 'FIG: \1') end end
replace(string, &block)
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 83 def replace(string, &block) string.instance_eval do alias :s :gsub! instance_eval(&block) end string end
required_commands()
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 67 def required_commands ['pandoc', 'xelatex'] end
tex_template()
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 79 def tex_template "#{Docfu::Skeleton.templates_location}/book.tex" end
verbatim_sanitize(string)
click to toggle source
# File lib/docfu/outputs/pdf.rb, line 91 def verbatim_sanitize(string) string.gsub('\\', '{\textbackslash}'). gsub('~', '{\textasciitilde}'). gsub(/([\$\#\_\^\%])/, '\\\\' + '\1{}') end