Weave.jl/src/rendering/texformats.jl

213 lines
6.4 KiB
Julia
Raw Normal View History

2020-05-30 17:49:20 +02:00
# PDF and Tex
# -----------
abstract type TexFormat <: WeaveFormat end
Base.@kwdef mutable struct JMarkdown2tex <: TexFormat
description = "Julia markdown to latex"
codestart = ""
codeend = ""
outputstart = "\\begin{lstlisting}"
outputend = "\\end{lstlisting}\n"
fig_ext = ".pdf"
extension = "tex"
mimetypes = ["application/pdf", "image/png", "image/jpg",
"text/latex", "text/markdown", "text/plain"]
keep_unicode = false
termstart = codestart
termend = codeend
2020-05-31 09:49:20 +02:00
out_width = "\\linewidth"
out_height = nothing
fig_pos = nothing
fig_env = nothing
highlight_theme = nothing
2020-05-30 17:49:20 +02:00
end
register_format!("md2tex", JMarkdown2tex())
2020-05-31 09:49:20 +02:00
Base.@kwdef mutable struct Tex <: TexFormat
description = "Latex with custom code environments"
codestart = "\\begin{juliacode}"
codeend = "\\end{juliacode}"
outputstart = "\\begin{juliaout}"
outputend = "\\end{juliaout}"
termstart = "\\begin{juliaterm}"
termend = "\\end{juliaterm}"
fig_ext = ".pdf"
extension = "tex"
fig_env = "figure"
fig_pos = "htpb"
mimetypes = ["application/pdf", "image/png", "text/latex", "text/plain"]
keep_unicode = false
2020-05-31 09:49:20 +02:00
out_width = "\\linewidth"
out_height = nothing
highlight_theme = nothing
end
register_format!("tex", Tex())
2020-05-31 09:49:20 +02:00
Base.@kwdef mutable struct TexMinted <: TexFormat
description = "Latex using minted for highlighting"
codestart =
"\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}"
codeend = "\\end{minted}"
outputstart =
"\\begin{minted}[fontsize=\\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}"
outputend = "\\end{minted}"
2020-05-31 09:49:20 +02:00
fig_ext = ".pdf"
extension = "tex"
mimetypes = ["application/pdf", "image/png", "text/latex", "text/plain"]
keep_unicode = false
termstart =
"\\begin{minted}[fontsize=\\footnotesize, xleftmargin=0.5em, mathescape]{jlcon}"
termend = "\\end{minted}"
out_width = "\\linewidth"
2020-05-31 09:49:20 +02:00
out_height = nothing
fig_env = "figure"
fig_pos = "htpb"
highlight_theme = nothing
end
register_format!("texminted", TexMinted())
2020-05-30 17:49:20 +02:00
2020-05-30 18:02:49 +02:00
isminted(::TexFormat) = false
isminted(::TexMinted) = true
2020-05-30 17:49:20 +02:00
2020-05-30 18:02:49 +02:00
function render_doc(docformat::TexFormat, body, doc, template, _, highlight_theme)
2020-05-30 17:49:20 +02:00
return Mustache.render(
get_tex_template(template);
body = body,
2020-05-30 18:02:49 +02:00
highlight = get_highlight_stylesheet(MIME("text/latex"), highlight_theme,
minted = isminted(docformat)),
2020-05-30 17:49:20 +02:00
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
)
end
# very similar to export to html
function format_chunk(chunk::DocChunk, docformat::TexFormat)
out = IOBuffer()
io = IOBuffer()
for inline in chunk.content
if isa(inline, InlineText)
write(io, inline.content)
elseif !isempty(inline.rich_output)
clear_buffer_and_format!(io, out, WeaveMarkdown.latex)
write(out, addlines(inline.rich_output, inline))
elseif !isempty(inline.figures)
write(io, inline.figures[end], inline)
elseif !isempty(inline.output)
write(io, addlines(inline.output, inline))
end
end
clear_buffer_and_format!(io, out, WeaveMarkdown.latex)
out = take2string!(out)
return docformat.keep_unicode ? out : uc2tex(out)
2020-05-30 17:49:20 +02:00
end
function format_output(result, docformat::TexFormat)
# Highligts has some extra escaping defined, eg of $, ", ...
result_escaped = sprint(
(io, x) ->
Highlights.Format.escape(io, MIME("text/latex"), x, charescape = true),
result,
)
docformat.keep_unicode || return uc2tex(result_escaped, true)
2020-05-30 17:49:20 +02:00
return result_escaped
end
# return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
function format_code(code, docformat::TexFormat)
ret = highlight_code(MIME("text/latex"), code, docformat.highlight_theme)
docformat.keep_unicode || return uc2tex(ret)
2020-05-30 17:49:20 +02:00
return ret
end
# Convert unicode to tex, escape listings if needed
function uc2tex(s, escape = false)
for key in keys(latex_symbols)
if escape
s = replace(s, latex_symbols[key] => "(*@\\ensuremath{$(texify(key))}@*)")
else
s = replace(s, latex_symbols[key] => "\\ensuremath{$(texify(key))}")
end
end
return s
end
# return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
format_termchunk(chunk, docformat::TexFormat) =
2020-05-31 09:49:20 +02:00
should_render(chunk) ? highlight_term(MIME("text/latex"), chunk.output, docformat.highlight_theme) : ""
2020-05-30 17:49:20 +02:00
function formatfigures(chunk, docformat::TexFormat)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
height = chunk.options[:out_height]
f_pos = chunk.options[:fig_pos]
f_env = chunk.options[:fig_env]
result = ""
figstring = ""
if f_env == nothing && caption != nothing
f_env = "figure"
end
(f_pos == nothing) && (f_pos = "!h")
# Set size
attribs = ""
width == nothing || (attribs = "width=$(md_length_to_latex(width,"\\linewidth"))")
(attribs != "" && height != nothing) && (attribs *= ",")
height == nothing || (attribs *= "height=$(md_length_to_latex(height,"\\paperheight"))")
if f_env != nothing
result *= "\\begin{$f_env}"
(f_pos != "") && (result *= "[$f_pos]")
result *= "\n"
end
for fig in fignames
if splitext(fig)[2] == ".tex" # Tikz figures
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
else
if isempty(attribs)
figstring *= "\\includegraphics{$fig}\n"
else
figstring *= "\\includegraphics[$attribs]{$fig}\n"
end
end
end
# Figure environment
if caption != nothing
result *= string("\\center\n", "$figstring", "\\caption{$caption}\n")
else
result *= figstring
end
if chunk.options[:label] != nothing && f_env != nothing
label = chunk.options[:label]
result *= "\\label{fig:$label}\n"
end
if f_env != nothing
result *= "\\end{$f_env}\n"
end
return result
end
function md_length_to_latex(def, reference)
if occursin("%", def)
_def = tryparse(Float64, replace(def, "%" => ""))
_def == nothing && return def
perc = round(_def / 100, digits = 2)
return "$perc$reference"
end
return def
end