Class: Softcover::Builders::Pdf

Inherits:
Softcover::Builder show all
Includes:
Output
Defined in:
lib/softcover/builders/pdf.rb

Constant Summary

Constants included from Utils

Utils::UNITS

Instance Attribute Summary

Attributes inherited from Softcover::Builder

#built_files, #manifest

Instance Method Summary collapse

Methods included from Output

should_output?, silence!, silent?, #system, unsilence!

Methods inherited from Softcover::Builder

#clean!, #initialize

Methods included from Utils

#add_highlight_class!, #as_size, #current_book, #digest, #executable, #execute, #in_book_directory?, #logged_in?, #mkdir, #path, #reset_current_book!, #rm, #silence, #source, #tmpify, #write_pygments_file

Constructor Details

This class inherits a constructor from Softcover::Builder

Instance Method Details

#build!(options = {}) ⇒ Object



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
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
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/softcover/builders/pdf.rb', line 6

def build!(options={})
  if manifest.markdown?
    # Build the HTML to produce PolyTeX as a side-effect,
    # then update the manifest to reduce PDF generation
    # to a previously solved problem.
    Softcover::Builders::Html.new.build!
    self.manifest = Softcover::BookManifest.new(source: :polytex,
                                                origin: :markdown)
  end
  # Build the PolyTeX filename so it accepts both 'foo' and 'foo.tex'.
  basename = File.basename(manifest.filename, '.tex')
  book_filename = basename + '.tex'

  # In debug mode, execute `xelatex` and exit.
  if options[:debug]
    execute "#{xelatex} #{book_filename}"
    return    # only gets called in test env
  elsif options[:'find-overfull']
    tmp_name = book_filename.sub('.tex', '.tmp.tex')
    # The we do things, code listings show up as "Overfull", but they're
    # actually fine, so filter them out.
    filter_out_listings = "grep -v 3.22281pt"
    # It's hard to correlate Overfull line numbers with source files,
    # so we use grep's -A flag to provide some context instead. Authors
    # can then use their text editors to find the corresponding place
    # in the text.
    show_context = 'grep -A 3 "Overfull \hbox"'
    cmd = "xelatex #{tmp_name} | #{filter_out_listings} | #{show_context}"
    execute cmd
    return
  end

  polytex_filenames = manifest.pdf_chapter_filenames << book_filename
  polytex_filenames.each do |filename|
    puts filename unless options[:quiet] || options[:silent]
    polytex = File.open(filename) { |f| f.read }
    latex   = Polytexnic::Pipeline.new(polytex).to_latex
    if filename == book_filename
      latex.gsub!(/\\include{(.*?)}/) do
        "\\include{#{Softcover::Utils.tmpify(manifest, $1)}.tmp}"
      end
    end
    File.open(Softcover::Utils.tmpify(manifest, filename), 'w') do |f|
      f.write(latex)
    end
  end
  write_pygments_file(:latex)
  copy_polytexnic_sty

  tmp_filename = Softcover::Utils.tmpify(manifest, book_filename)
  build_pdf = "#{xelatex} #{tmp_filename}"
  # Run the command twice (to guarantee up-to-date cross-references)
  # unless explicitly overriden.
  # Renaming the PDF in the command is necessary because `execute`
  # below uses `exec` (except in tests, where it breaks). Since `exec`
  # causes the Ruby process to end, any Ruby code after `exec`
  # is ignored.
  # (The reason for using `exec` is so that LaTeX errors get emitted to
  # the screen rather than just hanging the process.)
  pdf_cmd = options[:once] ? build_pdf : "#{build_pdf} ; #{build_pdf}"
  cmd = "#{pdf_cmd} ; #{rename_pdf(basename)}"
  # Here we use `system` when making a preview because the preview command
  # needs to run after the main PDF build.
  if options[:quiet] || options[:silent]
    silence { options[:preview] ? system(cmd) : execute(cmd) }
  else
    options[:preview] ? system(cmd) : execute(cmd)
  end
end