class Asciidoctor::PDF::Converter

Public Instance Methods

add_outline(doc, num_levels = 2, toc_page_nums = [], num_front_matter_pages = 0, has_front_cover = false) click to toggle source
# 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) click to toggle source
# 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
Also aliased as: build_pdf_info_original
build_pdf_info_original(doc)
Alias for: build_pdf_info
convert_dlist(node) click to toggle source
# 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) click to toggle source
# 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