Class: Asciidoctor::PDF::Converter

Inherits:
Object
  • Object
show all
Includes:
NabeHelper
Defined in:
lib/asciidoctor/nabetani/horz-dlist.rb,
lib/asciidoctor/nabetani/pdf-outline.rb,
lib/asciidoctor/nabetani/pdf-custom-property.rb

Instance Method Summary collapse

Methods included from NabeHelper

get_node_attriute_float, get_node_attriute_float_array, three_state

Instance Method Details

#add_outline(doc, num_levels = 2, toc_page_nums = [], num_front_matter_pages = 0, has_front_cover = false) ⇒ Object



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
# File 'lib/asciidoctor/nabetani/pdf-outline.rb', line 15

def add_outline doc, num_levels = 2, toc_page_nums = [], num_front_matter_pages = 0, has_front_cover = false
  if ::String === num_levels
    if num_levels.include? ':'
      num_levels, expand_levels = num_levels.split ':', 2
      num_levels = num_levels.empty? ? (doc.attr 'toclevels', 2).to_i : num_levels.to_i
      expand_levels = expand_levels.to_i
    else
      num_levels = expand_levels = num_levels.to_i
    end
  else
    expand_levels = num_levels
  end
  front_matter_counter = RomanNumeral.new 0, :lower
  pagenum_labels = {}

  num_front_matter_pages.times do |n|
    pagenum_labels[n] = { P: (::PDF::Core::LiteralString.new front_matter_counter.next!.to_s) }
  end

  # add labels for each content page, which is required for reader's page navigator to work correctly
  (num_front_matter_pages..(page_count - 1)).each_with_index do |n, i|
    pagenum_labels[n] = { P: (::PDF::Core::LiteralString.new (i + 1).to_s) }
  end

  unless toc_page_nums.none? || (toc_title = doc.attr 'toc-title').nil_or_empty?
    toc_section = insert_toc_section doc, toc_title, toc_page_nums
  end

  outline.define do
    initial_pagenum = has_front_cover ? 2 : 1
    # FIXME: use sanitize: :plain_text once available
    keyname = "bookmark_include_title_page in theme-yaml"
    case three_state(document.theme.bookmark_include_title_page, keyname)
    when true
      doctitle = doc.header? ? doc.doctitle : (doc.attr 'untitled-label')
      doctitle ||= "title page"
      page title: (document.sanitize doctitle), destination: (document.dest_top has_front_cover ? 2 : 1)
    when false
      # nothing needs to happen
    else # nil
      if document.page_count >= initial_pagenum && (doctitle = doc.header? ? doc.doctitle : (doc.attr 'untitled-label'))
        page title: (document.sanitize doctitle), destination: (document.dest_top has_front_cover ? 2 : 1)
      end
    end
    # QUESTION is there any way to get add_outline_level to invoke in the context of the outline?
    document.add_outline_level self, doc.sections, num_levels, expand_levels
  end

  toc_section.parent.blocks.delete toc_section if toc_section

  catalog.data[:PageLabels] = state.store.ref Nums: pagenum_labels.flatten
  primary_page_mode, secondary_page_mode = PageModes[(doc.attr 'pdf-page-mode') || @theme.page_mode]
  catalog.data[:PageMode] = primary_page_mode
  catalog.data[:NonFullScreenPageMode] = secondary_page_mode if secondary_page_mode
  nil
end

#build_pdf_info(doc) ⇒ Object



7
8
9
10
11
12
13
14
15
16
# File 'lib/asciidoctor/nabetani/pdf-custom-property.rb', line 7

def build_pdf_info doc
  info = build_pdf_info_original(doc)
  keys = %w( Title Author Subject Keywords Producer Creator )
  keys.each do |key|
    val = doc.attr( ("pdf_"+key).downcase )
    next unless val
    info[ key.to_sym ] = val.to_s.as_pdf
  end
  info
end

#build_pdf_info_originalObject



6
# File 'lib/asciidoctor/nabetani/pdf-custom-property.rb', line 6

alias_method :build_pdf_info_original, :build_pdf_info

#convert_dlist(node) ⇒ Object



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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/asciidoctor/nabetani/horz-dlist.rb', line 49

def convert_dlist node
  add_dest_for_block node if node.id

  case (style = node.style)
  when 'unordered', 'ordered'
    if style == 'unordered'
      list_style = :ulist
      (markers = @list_bullets) << :disc
    else
      list_style = :olist
      (markers = @list_numerals) << 1
    end
    list = List.new node.parent, list_style
    stack_subject = node.has_role? 'stack'
    subject_stop = node.attr 'subject-stop', (stack_subject ? nil : ':'), false
    node.items.each do |subjects, dd|
      subject = [*subjects].first.text
      list_item_text = %(+++<strong>#{subject}#{(StopPunctRx.match? sanitize subject) ? '' : subject_stop}</strong>#{dd.text? ? "#{stack_subject ? '<br>' : ' '}#{dd.text}" : ''}+++)
      list_item = ListItem.new list, list_item_text
      dd.blocks.each {|it| list_item << it }
      list << list_item
    end
    convert_outline_list list
    markers.pop
  when 'horizontal'
    table_data = []
    term_padding = desc_padding = term_line_metrics = term_inline_format = term_kerning = nil
    max_term_width = 0
    theme_font :description_list_term do
      if (term_font_styles = font_styles).empty?
        term_inline_format = true
      else
        term_inline_format = [inherited: { styles: term_font_styles }]
      end
      margin_left = get_node_attriute_float(node, 'margin-left', 10)
      margin_bottom = get_node_attriute_float(node, 'margin-bottom', (@theme.prose_margin_bottom || 0) * 0.5 )
      term_line_metrics = calc_line_metrics @theme.description_list_term_line_height || @theme.base_line_height
      term_padding = [
        term_line_metrics.padding_top, # up
        10, # right
        margin_bottom + term_line_metrics.padding_bottom, # bottom
        margin_left # left
      ]
      desc_padding = [
        0, # up
        10, # right
        margin_bottom, # bottom
        10 # left
      ]
      term_kerning = default_kerning?
    end
    node.items.each do |terms, desc|
      term_text = terms.map(&:text).join ?\n
      if (term_width = width_of term_text, inline_format: term_inline_format, kerning: term_kerning) > max_term_width
        max_term_width = term_width
      end
      row_data = [{
        text_color: @font_color,
        kerning: term_kerning,
        content: term_text,
        inline_format: term_inline_format,
        padding: term_padding,
        leading: term_line_metrics.leading,
        # FIXME: prawn-table doesn't have support for final_gap option
        #final_gap: term_line_metrics.final_gap,
        valign: :top,
      }]
      desc_container = Block.new desc, :open
      desc_container << (Block.new desc_container, :paragraph, source: (desc.instance_variable_get :@text), subs: :default) if desc.text?
      desc.blocks.each {|b| desc_container << b } if desc.block?
      row_data << {
        content: (::Prawn::Table::Cell::AsciiDoc.new self, content: desc_container, text_color: @font_color, padding: desc_padding, valign: :top),
      }
      table_data << row_data
    end
    max_term_width += (term_padding[1] + term_padding[3])
    term_column_width = [max_term_width, bounds.width * 0.5].min
    table table_data, position: :left, cell_style: { border_width: 0 }, column_widths: [term_column_width] do
      @pdf.layout_table_caption node if node.title?
    end
    margin_bottom 0 # (@theme.prose_margin_bottom || 0) * 0.5
  when 'qanda'
    @list_numerals << '1'
    convert_outline_list node
    @list_numerals.pop
  else
    # TODO: check if we're within one line of the bottom of the page
    # and advance to the next page if so (similar to logic for section titles)
    layout_caption node.title, category: :description_list if node.title?

    term_line_height = @theme.description_list_term_line_height || @theme.base_line_height
    line_metrics = theme_font(:description_list_term) { calc_line_metrics term_line_height }
    node.items.each do |terms, desc|
      # NOTE: don't orphan the terms (keep together terms and at least one line of content)
      allocate_space_for_list_item line_metrics, (terms.size + 1), ((@theme.description_list_term_spacing || 0) + 0.05)
      theme_font :description_list_term do
        if (term_font_styles = font_styles).empty?
          term_font_styles = nil
        end
        terms.each do |term|
          # QUESTION should we pass down styles in other calls to layout_prose
          layout_prose term.text, margin_top: 0, margin_bottom: @theme.description_list_term_spacing, align: :left, line_height: term_line_height, normalize_line_height: true, styles: term_font_styles
        end
      end
      indent(@theme.description_list_description_indent || 0) do
        traverse_list_item desc, :dlist_desc, normalize_line_height: true
      end if desc
    end
  end
end

#convert_paragraph(node) ⇒ Object



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
# File 'lib/asciidoctor/nabetani/horz-dlist.rb', line 8

def convert_paragraph node
  add_dest_for_block node if node.id
  prose_opts = { margin_bottom: 0, hyphenate: true }
  lead = (roles = node.roles).include? 'lead'
  if (align = resolve_alignment_from_role roles)
    prose_opts[:align] = align
  end

  if (text_indent = @theme.prose_text_indent || 0) > 0
    prose_opts[:indent_paragraphs] = text_indent
  end

  # TODO: check if we're within one line of the bottom of the page
  # and advance to the next page if so (similar to logic for section titles)
  layout_caption node.title if node.title?

  if lead
    theme_font :lead do
      layout_prose node.content, prose_opts
    end
  else
    layout_prose node.content, prose_opts
  end

  dlist = node&.parent&.parent&.parent

  if dlist&.style=="horizontal"
    m = get_node_attriute_float( dlist, "margin-bottom", nil )
    if m
      margin_bottom m
      return
    end
  end
  if (margin_inner_val = @theme.prose_margin_inner) &&
      (next_block = (siblings = node.parent.blocks)[(siblings.index node) + 1]) && next_block.context == :paragraph
    margin_bottom margin_inner_val
  else
    margin_bottom @theme.prose_margin_bottom
  end
end