markdown2 :: markdown_latex_rendering $ MdFencedCodeBlock
A code block that starts with a fencemarkdown2 :: markdown_latex_rendering $ MdHtmlInline
An inlined html stringmarkdown2 :: markdown_latex_rendering $ MdIndentedCodeBlock
A block code that starts with an indentmarkdown2 :: markdown_latex_rendering $ MdLineBreak
A line break (soft or hard)markdown2 :: markdown_latex_rendering $ MdListItem
An ordered or unordered list item blockmarkdown2 :: markdown_latex_rendering $ MdOrderedList
An ordered list blockmarkdown2 :: markdown_latex_rendering $ MdStrongEmphasis
A strong emphasis tokenmarkdown2 :: markdown_latex_rendering $ MdUnorderedList
An unordered listmarkdown2 :: markdown_latex_rendering $ MdFencedCodeBlock
A code block that starts with a fencemarkdown2 :: markdown_latex_rendering $ MdHtmlInline
An inlined html stringmarkdown2 :: markdown_latex_rendering $ MdIndentedCodeBlock
A block code that starts with an indentmarkdown2 :: markdown_latex_rendering $ MdLineBreak
A line break (soft or hard)markdown2 :: markdown_latex_rendering $ MdListItem
An ordered or unordered list item blockmarkdown2 :: markdown_latex_rendering $ MdOrderedList
An ordered list blockmarkdown2 :: markdown_latex_rendering $ MdStrongEmphasis
A strong emphasis tokenmarkdown2 :: markdown_latex_rendering $ MdUnorderedList
An unordered listcore :: union_find
union–find algorithm using an efficient disjoint-set data structure
# LaTeX rendering of Markdown documents
module markdown_latex_rendering
import markdown_rendering
import markdown_github
import markdown_wikilinks
# Markdown document renderer to LaTeX
class LatexRenderer
super MdRenderer
# Generate the LaTeX document wrapper
#
# The header includes:
# * document class
# * package importation
# * begin and end document directives
var wrap_document = false is optional, writable
# LaTeX document class
#
# Default is `article`.
var document_class = "article" is optional, writable
# LaTeX document page format
#
# Default is `letter`.
var page_format = "letter" is optional, writable
# LaTeX font size
#
# Default is `10pt`.
var font_size = "10pt" is optional, writable
# Use `listings` package for code blocks?
var use_listings = false is optional, writable
# LaTeX output under construction
private var latex: Buffer is noinit
# Render `document` as LaTeX
redef fun render(document) do
latex = new Buffer
enter_visit(document)
return latex.write_to_string
end
redef fun visit(node) do node.render_latex(self)
# Indentation level
var indent = 0
# Add a raw `string` to the output
#
# Raw means that the string will not be escaped.
fun add_raw(string: String) do latex.append string
# Add `text` string to the output
#
# The string will be escaped.
fun add_text(text: String) do latex.append latex_escape(text)
# Add a blank line to the output
fun add_line do
if not latex.is_empty and latex.last != '\n' then
latex.add '\n'
end
end
# Add an indentation depending on `ident` level
fun add_indent do latex.append " " * indent
# Escape `string` to LaTeX
fun latex_escape(string: String): String do
var buffer = new Buffer
for i in [0 .. string.length[ do
var c = string.chars[i]
if c == '>' then
buffer.append "\\textgreater"
continue
else if c == '<' then
buffer.append "\\textless"
continue
else if c == '\\' then
buffer.append "\\textbackslash"
continue
else if escaped_chars.has(c) then
buffer.add '\\'
end
buffer.add c
end
return buffer.to_s
end
# LaTeX characters to escape
var escaped_chars = ['%', '$', '{', '}', '_', '#', '&']
end
redef class MdNode
# Render `self` as HTML
fun render_latex(v: LatexRenderer) do visit_all(v)
end
# Blocks
redef class MdDocument
redef fun render_latex(v) do
var wrap_document = v.wrap_document
if v.wrap_document then
v.add_line
v.add_raw "\\documentclass[{v.page_format},{v.font_size}]\{{v.document_class}\}\n\n"
v.add_raw "\\usepackage[utf8]\{inputenc\}\n"
if v.use_listings then
v.add_raw "\\usepackage\{listings\}\n"
end
v.add_raw "\\usepackage\{hyperref\}\n"
v.add_raw "\\usepackage\{graphicx\}\n"
v.add_raw "\\usepackage\{ulem\}\n\n"
v.add_raw "\\begin\{document\}\n\n"
end
var node = first_child
while node != null do
v.enter_visit node
node = node.next
if node != null then v.add_raw "\n"
end
if wrap_document then
v.add_raw "\n\\end\{document\}\n"
end
end
end
redef class MdHeading
redef fun render_latex(v) do
var level = self.level
v.add_indent
v.add_line
if level == 1 then
v.add_raw "\\section\{"
else if level == 2 then
v.add_raw "\\subsection\{"
else if level == 3 then
v.add_raw "\\subsubsection\{"
else if level == 4 then
v.add_raw "\\paragraph\{"
else if level == 5 then
v.add_raw "\\subparagraph\{"
else
# use bold for level 6 headings
v.add_raw "\\textbf\{"
end
v.add_indent
visit_all(v)
v.add_raw "\}"
v.add_line
end
end
redef class MdBlockQuote
redef fun render_latex(v) do
v.add_line
v.add_indent
v.add_raw "\\begin\{quote\}"
v.add_line
v.indent += 2
visit_all(v)
v.indent -= 2
v.add_line
v.add_indent
v.add_raw "\\end\{quote\}"
v.add_line
end
end
redef class MdIndentedCodeBlock
redef fun render_latex(v) do
var directive = if v.use_listings then "lstlisting" else "verbatim"
v.add_line
v.add_indent
v.add_raw "\\begin\{{directive}\}"
v.add_line
v.add_raw literal or else ""
v.add_line
v.add_indent
v.add_raw "\\end\{{directive}\}"
v.add_line
end
end
redef class MdFencedCodeBlock
redef fun render_latex(v) do
var info = self.info
var lstlistings = v.use_listings
var directive = if lstlistings then "lstlisting" else "verbatim"
v.add_line
v.add_indent
v.add_raw "\\begin\{{directive}\}"
if lstlistings and info != null and not info.is_empty then
v.add_raw "[language={info}]"
end
v.add_line
v.add_raw literal or else ""
v.add_line
v.add_indent
v.add_raw "\\end\{{directive}\}"
v.add_line
end
end
redef class MdOrderedList
redef fun render_latex(v) do
var start = self.start_number
v.add_line
v.add_indent
v.add_raw "\\begin\{enumerate\}"
v.indent += 2
v.add_line
if start != 1 then
v.add_indent
v.add_raw "\\setcounter\{enum{nesting_level}\}\{{start}\}"
v.add_line
end
visit_all(v)
v.indent -= 2
v.add_line
v.add_indent
v.add_raw "\\end\{enumerate\}"
v.add_line
end
# Depth of ordered list
#
# Used to compute the `setcounter` level.
fun nesting_level: String do
var nesting = 1
var parent = self.parent
while parent != null do
if parent isa MdOrderedList then nesting += 1
parent = parent.parent
end
if nesting <= 3 then
return "i" * nesting
end
return "iv"
end
end
redef class MdUnorderedList
redef fun render_latex(v) do
v.add_line
v.add_indent
v.add_raw "\\begin\{itemize\}"
v.add_line
v.indent += 2
visit_all(v)
v.indent -= 2
v.add_line
v.add_indent
v.add_raw "\\end\{itemize\}"
v.add_line
end
end
redef class MdListItem
redef fun render_latex(v) do
v.add_indent
v.add_raw "\\item"
v.add_line
v.indent += 2
visit_all(v)
v.indent -= 2
v.add_line
end
end
redef class MdThematicBreak
redef fun render_latex(v) do
v.add_line
v.add_indent
v.add_raw "\\begin\{center\}\\rule\{3in\}\{0.4pt\}\\end\{center\}"
v.add_line
end
end
redef class MdParagraph
redef fun render_latex(v) do
v.add_indent
visit_all(v)
v.add_line
end
end
redef class MdHtmlBlock
redef fun render_latex(v) do
v.add_line
v.add_indent
v.add_raw "\\begin\{verbatim\}"
v.add_line
v.add_indent
v.add_raw literal or else ""
v.add_line
v.add_indent
v.add_raw "\\end\{verbatim\}"
v.add_line
end
end
# Inlines
redef class MdLineBreak
redef fun render_latex(v) do
v.add_line
v.add_indent
end
end
redef class MdCode
redef fun render_latex(v) do
v.add_raw "\\texttt\{"
v.add_text literal
v.add_raw "\}"
end
end
redef class MdEmphasis
redef fun render_latex(v) do
v.add_raw "\\textit\{"
visit_all(v)
v.add_raw "\}"
end
end
redef class MdStrongEmphasis
redef fun render_latex(v) do
v.add_raw "\\textbf\{"
visit_all(v)
v.add_raw "\}"
end
end
redef class MdHtmlInline
redef fun render_latex(v) do
v.add_raw "\\texttt\{"
v.add_raw v.latex_escape(literal)
v.add_raw "\}"
end
end
redef class MdImage
redef fun render_latex(v) do
v.add_raw "\\includegraphics\{"
v.add_text destination
v.add_raw "\}"
end
private fun alt_text: String do
var v = new RawTextVisitor
return v.render(self)
end
end
redef class MdLink
redef fun render_latex(v) do
if is_autolink then
v.add_raw "\\url\{"
v.add_text destination
v.add_raw "\}"
return
end
var title = self.title
v.add_raw "\\href\{"
v.add_text destination
v.add_raw "\}\{"
visit_all(v)
if title != null and not title.is_empty then
v.add_raw " ("
v.add_text title
v.add_raw ")"
end
v.add_raw "\}"
end
end
redef class MdText
redef fun render_latex(v) do
v.add_text literal
end
end
# Github mode
redef class MdStrike
redef fun render_latex(v) do
v.add_raw "\\sout\{"
visit_all(v)
v.add_raw "\}"
end
end
redef class MdSuper
redef fun render_latex(v) do
v.add_raw "\\textsuperscript\{"
visit_all(v)
v.add_raw "\}"
end
end
# Wikilinks
redef class MdWikilink
redef fun render_latex(v) do
v.add_raw "\\texttt\{"
var title = self.title
if title != null then
v.add_text "{title} | "
end
v.add_text link
v.add_raw "\}"
end
end
lib/markdown2/markdown_latex_rendering.nit:15,1--438,3