Class: Any2Pdf

Inherits:
Object
  • Object
show all
Defined in:
lib/any2pdf/style.rb,
lib/any2pdf/md2html.rb,
lib/any2pdf/html2pdf.rb,
lib/any2pdf/metadata.rb

Instance Method Summary collapse

Instance Method Details

#embed_html(raw, source) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/any2pdf/md2html.rb', line 4

def embed_html( raw, source )
  begin
    require 'websnap'
    w = WebSnap.new( nil, nil )

    # parse raw html contents
    Log.info "embedding html via websnap"
    h = Nokogiri::HTML(raw)

    # embed all parts into the html
    w.spiderHtmlElements( 'file://'+File::expand_path(source), h )

    # return the resulting html as string
    h.to_s
  rescue LoadError
    return raw
  end
end

#fill_in_metadata(path, tmpfile) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/any2pdf/metadata.rb', line 3

def ( path, tmpfile )
  tag = `git describe --tags --abbrev=0`.chomp
  gitlog = `git log -1 --pretty=format:'%h %ct'`
  commit, date = gitlog.split(" ")
  if commit == "" || date == nil
    Log.warn "Can't find git info for latest commit. Ignoring."
    return path
  end
  Log.info "Adding git metadata: #{tag} #{commit} #{date}"

  time = Time.at( date.to_i )
  timestamp = "%04d-%02d-%02d" % [ time.year, time.month, time.day ]

  content = File::read(path)
  info = ["---",
    "git_commit: #{commit}",
    "git_date: #{timestamp}",
    (tag == "" ) ? nil : "git_tag: #{tag}"
    ].compact.join("\n") + "\n"

  if content.start_with?("---\n")
    nu = content.sub("---\n",info)
  else
    nu = info + "---\n" + content
  end

  File::write( tmpfile, nu )
  tmpfile
end

#get_style(stylename, type = "css") ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/any2pdf/style.rb', line 2

def get_style( stylename, type = "css" )
  rel_path = File.expand_path('../../data', File.dirname(__FILE__))

  if not stylename.nil? and not stylename.empty?
    a =
      get_existing(stylename) ||
      get_existing("#{rel_path}/#{stylename}.#{type}") ||
      get_existing("#{rel_path}/#{stylename}")
    return a if not a.nil?
    Log.warn "couldn't find stylesheet #{stylename}. Trying default.\n"
  end

  # try default, if the user supplied crap...
  a = get_existing("#{rel_path}/default.#{type}")
  return a if not a.nil?
  Log.error "Couldn't find internal stylesheet in #{rel_path}/default.#{type}. Something is seriously wrong! try reinstalling?\n"
  ""
end

#html2pdf(file, opts) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/any2pdf/html2pdf.rb', line 71

def html2pdf(file, opts)
  Log.debug "running html2pdf on '#{file}'"
  return nil if not file.end_with?(".html")
  pdffile = file.sub(/.html$/,".pdf")
  pdffile = opts.output if not opts.output.nil? and not opts.output.empty?
  Log.debug "output pdf will be '#{pdffile}'"

  case opts[:renderer]
  when 'pdfkit'
    pdfkit_html2pdf file, pdffile, opts
  when 'xelatex'
    xelatex_html2pdf file, pdffile, opts
  else
    Log.abort "Can't find renderer '#{opts[:renderer]}'. Please use a supported renderer!"
  end

  pdffile
end

#md2html(file, outfile, opts, stylefile) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/any2pdf/md2html.rb', line 23

def md2html(file, outfile, opts, stylefile)
  return nil if not file.end_with?(".md")
  outfile_raw = outfile+".raw.html"

  rel_path = File.expand_path('../../data', File.dirname(__FILE__))

  # prep-work for including style and script
  style_e = lambda{|f,o| "<style type=\"text/css\" #{o}>\n#{File::read(f)}\n</style>" }
  style_l = lambda{|f,o| "<link rel=\"stylesheet\" href=\"#{f}\" #{o} />" }
  script_e = lambda{|f,o| "<script #{o}>\n#{File::read(f)}\n</script>" }
  script_l = lambda{|f,o| "<script src=\"#{f}\" #{o} ></script>"}
  style = opts[:embed] ? style_e : style_l
  script = opts[:embed] ? script_e : script_l

  # get all fields in the heading
  raw_heading = [
    # start with stylesheets
    style.( rel_path+"/boilerplate.css", ''),
    style.( File::expand_path(stylefile), '' ),
    style.( rel_path+"/print.css", 'media="print"'),
    script.( rel_path+"/jquery-1.9.0.min.js", '' ),
    ( opts[:toc] ? script.( rel_path+"/toc_generator.js", '' ) : '' )
    ].join("\n\n")

  # create the html
  `pandoc "#{file}" -o "#{outfile_raw}" --template #{rel_path}/pandoc-template.html --toc`
  raw_html = File::read outfile_raw
  File.delete outfile_raw

  # additional options
  toc_level = opts[:toc_level]
  number_headings = (opts[:numbering] == true)

  # actually create the result file
  renderer = ERB.new(File::read(rel_path + "/template.html.erb"))
  html = embed_html( renderer.result(binding), file )
  
  # save the html to file
  File::write outfile, html
  outfile
end

#pdfkit_html2pdf(file, outfile, opts) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/any2pdf/html2pdf.rb', line 7

def pdfkit_html2pdf( file, outfile, opts )
  styles = []
  styles << opts.stylesheet

  style_opts = get_style_options opts.stylesheet

  # find css files
  dom = Nokogiri::parse( File::open(file).read() )
  dom.css("link").each do |e| 
    styles << e.attr("href")
  end

  # update the html links to make sure that local links (relative) work
  ( dom.css("@src") + dom.css("@href") ).
    find_all{|src| (src.value =~ URI::regexp) == nil }.
    each{|src| src.value = File::expand_path(src.value) }

  options = {
    footer_right:   "[page]/[topage]",
    orientation:    (( opts[:landscape] ) ? "landscape" : "portrait" ),
    page_size:      'A4',
  }.merge(style_opts)
  html = dom.to_s
  kit = PDFKit.new(html, options)

  styles.compact.each do |style| 
    kit.stylesheets << style if File::exists?(style)
  end

  kit.to_file(outfile)
end

#xelatex_html2pdf(file, outfile, opts) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/any2pdf/html2pdf.rb', line 39

def xelatex_html2pdf( file, outfile, opts )
  puts outfile
  texfile = "#{outfile}".sub(/[.]pdf$/, '.tex')

  cmd = "pandoc \"#{file}\" --listings -o \"#{texfile}\""
  Log.debug "convert html to tex: #{cmd}"
  `#{cmd}`

  verb_opts = "mathescape,
               linenos,
               numbersep=5pt,
               frame=single,
               framesep=1mm,
               bgcolor=colorcode_bg".gsub("\n",'')

  tex = File::read(texfile).
    # all verbatim stuff is in lstlistings like this:
    # \begin{lstlisting}[language=bash]
    # convert it to minted
    gsub(/\\begin{lstlisting}\[language=([^\]]*)\]/){'\begin{minted}['+verb_opts+']{'+$1+'}'}.
    gsub(/\\begin{lstlisting}/, '\begin{minted}['+verb_opts+']{bash}').
    gsub(/\\lstinline(.)(.*?)\1/){ '\colorbox{colorcode_bg}{\lstinline'+$1+$2+$1+'}' }.
    gsub(/\\end{lstlisting}/, '\end{minted}')

  tex_style = get_style( opts[:stylesheet], 'tex' )
  File::write texfile, File::read(tex_style).sub(/CONTENT/, tex)

  cmd = "xelatex -shell-escape \"#{texfile}\""
  Log.debug "convert tex to pdf: #{cmd}"
  `#{cmd}`
end