# class Kramdown::Converter::Latex

Converts an element tree to LaTeX.

This converter uses ideas from other Markdown-to-LaTeX converters like Pandoc and Maruku.

You can customize this converter by sub-classing it and overriding the `convert_NAME` methods. Each such method takes the following parameters:

`el`

  The element of type `NAME` to be converted.

`opts`

  A hash containing processing options that are passed down from parent elements. The key :parent is always set and contains the parent element as value.

The return value of such a method has to be a string containing the element `el` formatted correctly as LaTeX markup.

### Public Class Methods

new(root, options) click to toggle source

Initialize the LaTeX converter with the `root` element and the conversion `options`.

Calls superclass method `Kramdown::Converter::Base::new`

       # File lib/kramdown/converter/latex.rb
    33 def initialize(root, options)
    34   super
    35   @data[:packages] = Set.new
    36 end

### Public Instance Methods

attribute_list(el) click to toggle source

Return a LaTeX comment containing all attributes as ‘key=“value”’ pairs.

        # File lib/kramdown/converter/latex.rb
    599 def attribute_list(el)
    600   attrs = el.attr.map {|k, v| v.nil? ? '' : " #{k}=\"#{v}\"" }.compact.sort.join
    601   attrs = "   % #{attrs}" unless attrs.empty?
    602   attrs
    603 end

convert(el, opts = {}) click to toggle source

Dispatch the conversion of the element `el` to a `convert_TYPE` method using the `type` of the element.

       # File lib/kramdown/converter/latex.rb
    40 def convert(el, opts = {})
    41   send("convert_#{el.type}", el, opts)
    42 end

convert_a(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    216 def convert_a(el, opts)
    217   url = el.attr['href']
    218   if url.start_with?('#')
    219     "\\hyperlink{#{url[1..-1].gsub('%', '\\%')}}{#{inner(el, opts)}}"
    220   else
    221     "\\href{#{url.gsub('%', '\\%')}}{#{inner(el, opts)}}"
    222   end
    223 end

convert_abbreviation(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    569 def convert_abbreviation(el, _opts)
    570   @data[:packages] += %w[acronym]
    571   "\\ac{#{normalize_abbreviation_key(el.value)}}"
    572 end

convert_blank(_el, opts) click to toggle source

       # File lib/kramdown/converter/latex.rb
    60 def convert_blank(_el, opts)
    61   opts[:result].match?(/\n\n\Z|\A\Z/) ? "" : "\n"
    62 end

convert_blockquote(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    109 def convert_blockquote(el, opts)
    110   latex_environment(el.children.size > 1 ? 'quotation' : 'quote', el, inner(el, opts))
    111 end

convert_br(_el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    209 def convert_br(_el, opts)
    210   res = +"\\newline"
    211   res << "\n" if (c = opts[:parent].children[opts[:index] + 1]) &&
    212     (c.type != :text || c.value !~ /^\s*\n/)
    213   res
    214 end

convert_codeblock(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
     86 def convert_codeblock(el, _opts)
     87   show_whitespace = el.attr['class'].to_s =~ /\bshow-whitespaces\b/
     88   lang = extract_code_language(el.attr)
     89
     90   if @options[:syntax_highlighter] == :minted &&
     91       (highlighted_code = highlight_code(el.value, lang, :block))
     92     @data[:packages] << 'minted'
     93     "#{latex_link_target(el)}#{highlighted_code}\n"
     94   elsif show_whitespace || lang
     95     options = []
     96     options << (show_whitespace ? "showspaces=true,showtabs=true" : "showspaces=false,showtabs=false")
     97     options << "language=#{lang}" if lang
     98     options << "basicstyle=\\ttfamily\\footnotesize,columns=fixed,frame=tlbr"
     99     id = el.attr['id']
    100     options << "label=#{id}" if id
    101     attrs = attribute_list(el)
    102     "#{latex_link_target(el)}\\begin{lstlisting}[#{options.join(',')}]\n" \
    103       "#{el.value}\n\\end{lstlisting}#{attrs}\n"
    104   else
    105     "#{latex_link_target(el)}\\begin{verbatim}#{el.value}\\end{verbatim}\n"
    106   end
    107 end

convert_codespan(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    239 def convert_codespan(el, _opts)
    240   lang = extract_code_language(el.attr)
    241   if @options[:syntax_highlighter] == :minted &&
    242       (highlighted_code = highlight_code(el.value, lang, :span))
    243     @data[:packages] << 'minted'
    244     "#{latex_link_target(el)}#{highlighted_code}"
    245   else
    246     "\\texttt{#{latex_link_target(el)}#{escape(el.value)}}"
    247   end
    248 end

convert_comment(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    205 def convert_comment(el, _opts)
    206   el.value.split("\n").map {|l| "% #{l}" }.join("\n") << "\n"
    207 end

convert_dd(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    150 def convert_dd(el, opts)
    151   "#{latex_link_target(el)}#{inner(el, opts)}\n\n"
    152 end

convert_dl(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    138 def convert_dl(el, opts)
    139   latex_environment('description', el, inner(el, opts))
    140 end

convert_dt(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    146 def convert_dt(el, opts)
    147   "\\item[#{inner(el, opts)}] "
    148 end

convert_em(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    263 def convert_em(el, opts)
    264   "\\emph{#{latex_link_target(el)}#{inner(el, opts)}}"
    265 end

convert_entity(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    533 def convert_entity(el, _opts)
    534   entity_to_latex(el.value)
    535 end

convert_footnote(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    250 def convert_footnote(el, opts)
    251   @data[:packages] << 'fancyvrb'
    252   "\\footnote{#{inner(el.value, opts).rstrip}}"
    253 end

convert_header(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    113 def convert_header(el, opts)
    114   type = @options[:latex_headers][output_header_level(el.options[:level]) - 1]
    115   if ((id = el.attr['id']) ||
    116       (@options[:auto_ids] && (id = generate_id(el.options[:raw_text])))) && in_toc?(el)
    117     "\\#{type}{#{inner(el, opts)}}\\hypertarget{#{id}}{}\\label{#{id}}\n\n"
    118   else
    119     "\\#{type}*{#{inner(el, opts)}}\n\n"
    120   end
    121 end

convert_hr(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    123 def convert_hr(el, _opts)
    124   attrs = attribute_list(el)
    125   "#{latex_link_target(el)}\\begin{center}#{attrs}\n\\rule{3in}{0.4pt}\n\\end{center}#{attrs}\n"
    126 end

convert_html_element(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    154 def convert_html_element(el, opts)
    155   case el.value
    156   when 'i', 'em'
    157     "\\emph{#{inner(el, opts)}}"
    158   when 'b', 'strong'
    159     "\\textbf{#{inner(el, opts)}}"
    160   else
    161     warning("Can't convert HTML element")
    162     ''
    163   end
    164 end

convert_img(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    225 def convert_img(el, _opts)
    226   line = el.options[:location]
    227   if el.attr['src'].match?(/^(https?|ftps?):\/\//)
    228     warning("Cannot include non-local image#{line ? " (line #{line})" : ''}")
    229     ''
    230   elsif !el.attr['src'].empty?
    231     @data[:packages] << 'graphicx'
    232     "#{latex_link_target(el)}\\includegraphics{#{el.attr['src']}}"
    233   else
    234     warning("Cannot include image with empty path#{line ? " (line #{line})" : ''}")
    235     ''
    236   end
    237 end

convert_li(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    142 def convert_li(el, opts)
    143   "\\item{} #{latex_link_target(el, true)}#{inner(el, opts).sub(/\n+\Z/, '')}\n"
    144 end

convert_math(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    556 def convert_math(el, _opts)
    557   @data[:packages] += %w[amssymb amsmath amsthm amsfonts]
    558   if el.options[:category] == :block
    559     if el.value.match?(/\A\s*\\begin\{/)
    560       el.value
    561     else
    562       latex_environment('displaymath', el, el.value)
    563     end
    564   else
    565     "$#{el.value}$"
    566   end
    567 end

convert_ol(el, opts)
Alias for: convert_ul
convert_p(el, opts) click to toggle source

       # File lib/kramdown/converter/latex.rb
    68 def convert_p(el, opts)
    69   if el.children.size == 1 && el.children.first.type == :img &&
    70       !(img = convert_img(el.children.first, opts)).empty?
    71     convert_standalone_image(el, opts, img)
    72   else
    73     "#{latex_link_target(el)}#{inner(el, opts)}\n\n"
    74   end
    75 end

convert_raw(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    255 def convert_raw(el, _opts)
    256   if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('latex')
    257     el.value + (el.options[:category] == :block ? "\n" : '')
    258   else
    259     ''
    260   end
    261 end

convert_root(el, opts) click to toggle source

       # File lib/kramdown/converter/latex.rb
    56 def convert_root(el, opts)
    57   inner(el, opts)
    58 end

convert_smart_quote(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    550 def convert_smart_quote(el, opts)
    551   res = entity_to_latex(smart_quote_entity(el)).chomp('{}')
    552   res << "{}" if ((nel = opts[:parent].children[opts[:index] + 1]) && nel.type == :smart_quote) || res =~ /\w$/
    553   res
    554 end

convert_standalone_image(el, _opts, img) click to toggle source

Helper method used by `convert_p` to convert a paragraph that only contains a single :img element.

       # File lib/kramdown/converter/latex.rb
    79 def convert_standalone_image(el, _opts, img)
    80   attrs = attribute_list(el)
    81   "\\begin{figure}#{attrs}\n\\begin{center}\n#{img}\n\\end{center}\n" \
    82     "\\caption{#{escape(el.children.first.attr['alt'])}}\n" \
    83     "#{latex_link_target(el, true)}\n\\end{figure}#{attrs}\n"
    84 end

convert_strong(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    267 def convert_strong(el, opts)
    268   "\\textbf{#{latex_link_target(el)}#{inner(el, opts)}}"
    269 end

convert_table(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    177 def convert_table(el, opts)
    178   @data[:packages] << 'longtable'
    179   align = el.options[:alignment].map {|a| TABLE_ALIGNMENT_CHAR[a] }.join('|')
    180   attrs = attribute_list(el)
    181   "#{latex_link_target(el)}\\begin{longtable}{|#{align}|}#{attrs}\n" \
    182     "\\hline\n#{inner(el, opts)}\\hline\n\\end{longtable}#{attrs}\n\n"
    183 end

convert_tbody(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    189 def convert_tbody(el, opts)
    190   inner(el, opts)
    191 end

convert_td(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    201 def convert_td(el, opts)
    202   inner(el, opts)
    203 end

convert_text(el, _opts) click to toggle source

       # File lib/kramdown/converter/latex.rb
    64 def convert_text(el, _opts)
    65   escape(el.value)
    66 end

convert_tfoot(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    193 def convert_tfoot(el, opts)
    194   "\\hline \\hline \n#{inner(el, opts)}"
    195 end

convert_thead(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    185 def convert_thead(el, opts)
    186   "#{inner(el, opts)}\\hline\n"
    187 end

convert_tr(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    197 def convert_tr(el, opts)
    198   el.children.map {|c| send("convert_#{c.type}", c, opts) }.join(' & ') << "\\\\\n"
    199 end

convert_typographic_sym(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    542 def convert_typographic_sym(el, _opts)
    543   if (result = @options[:typographic_symbols][el.value])
    544     escape(result)
    545   else
    546     TYPOGRAPHIC_SYMS[el.value]
    547   end
    548 end

convert_ul(el, opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    128 def convert_ul(el, opts)
    129   if !@data[:has_toc] && el.options.dig(:ial, :refs)&.include?('toc')
    130     @data[:has_toc] = true
    131     '\tableofcontents'
    132   else
    133     latex_environment(el.type == :ul ? 'itemize' : 'enumerate', el, inner(el, opts))
    134   end
    135 end

Also aliased as: convert_ol
convert_xml_comment(el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    166 def convert_xml_comment(el, _opts)
    167   el.value.split("\n").map {|l| "% #{l}" }.join("\n") + "\n"
    168 end

convert_xml_pi(_el, _opts) click to toggle source

        # File lib/kramdown/converter/latex.rb
    170 def convert_xml_pi(_el, _opts)
    171   warning("Can't convert XML PI")
    172   ''
    173 end

entity_to_latex(entity) click to toggle source

        # File lib/kramdown/converter/latex.rb
    522 def entity_to_latex(entity)
    523   text, package = ENTITY_CONV_TABLE[entity.code_point]
    524   if text
    525     @data[:packages] << package if package
    526     text
    527   else
    528     warning("Couldn't find entity with code #{entity.code_point} in substitution table!")
    529     ''
    530   end
    531 end

escape(str) click to toggle source

Escape the special LaTeX characters in the string `str`.

        # File lib/kramdown/converter/latex.rb
    618 def escape(str)
    619   str.gsub(ESCAPE_RE) {|m| ESCAPE_MAP[m] }
    620 end

inner(el, opts) click to toggle source

Return the converted content of the children of `el` as a string.

       # File lib/kramdown/converter/latex.rb
    45 def inner(el, opts)
    46   result = +''
    47   options = opts.dup.merge(parent: el)
    48   el.children.each_with_index do |inner_el, index|
    49     options[:index] = index
    50     options[:result] = result
    51     result << send("convert_#{inner_el.type}", inner_el, options)
    52   end
    53   result
    54 end

latex_environment(type, el, text) click to toggle source

Wrap the `text` inside a LaTeX environment of type `type`. The element `el` is passed on to the method `attribute_list` – the resulting string is appended to both the \begin and the \end lines of the LaTeX environment for easier post-processing of LaTeX environments.

        # File lib/kramdown/converter/latex.rb
    582 def latex_environment(type, el, text)
    583   attrs = attribute_list(el)
    584   "\\begin{#{type}}#{latex_link_target(el)}#{attrs}\n#{text.rstrip}\n\\end{#{type}}#{attrs}\n"
    585 end

latex_link_target(el, add_label = false) click to toggle source

Return a string containing a valid hypertarget command if the element has an ID defined, or `nil` otherwise. If the parameter `add_label` is `true`, a label command will also be used additionally to the hypertarget command.

        # File lib/kramdown/converter/latex.rb
    590 def latex_link_target(el, add_label = false)
    591   if (id = el.attr['id'])
    592     "\\hypertarget{#{id}}{}#{add_label ? "\\label{#{id}}" : ''}"
    593   else
    594     nil
    595   end
    596 end

normalize_abbreviation_key(key) click to toggle source

Normalize the abbreviation key so that it only contains allowed ASCII character

        # File lib/kramdown/converter/latex.rb
    575 def normalize_abbreviation_key(key)
    576   key.gsub(/\W/) {|m| m.unpack1('H*') }
    577 end