1
2
3
4
5
6
7
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
48
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
use pulldown_cmark::{Event, Parser, Tag};

pub const LATEX_HEADER:&str = r#"\documentclass{scrartcl}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage{listings}
\usepackage{xcolor}
\definecolor{colKeys}{rgb}{0,0.5,0}
\definecolor{colIdentifier}{rgb}{0,0,0}
\definecolor{colComments}{rgb}{0,0.5,1}
\definecolor{colString}{rgb}{0.6,0.1,0.1}
\definecolor{colBackground}{rgb}{0.95,0.95,1}
\lstset{%configuration de listings
   float=hbp,%
   basicstyle=\ttfamily\small,%
   %
   identifierstyle=\color{colIdentifier}, %
   keywordstyle=\color{colKeys}, %
   stringstyle=\color{colString}, %
   commentstyle=\color{colComments}\textit, %
   %
   backgroundcolor=\color{colBackground},%
   %
   columns=flexible, %
   tabsize=2, %
   frame=trbl, %
   %frameround=tttt,%
   extendedchars=true, %
   showspaces=false, %
   showstringspaces=false, %
   numbers=left, %
   numberstyle=\tiny, %
   breaklines=true, %
   breakautoindent=true, %
   captionpos=b,%
   xrightmargin=0.2cm, %
   xleftmargin=0.2cm
}
\begin{document}
"#;

pub const LATEX_FOOTER: &str = "\n\\end{document}\n";

pub fn markdown_to_latex(markdown: String) -> String {
    let mut output = String::from(LATEX_HEADER);

    let parser = Parser::new(&markdown);

    for event in parser {
        match event {
            Event::Start(Tag::Header(level)) => {
                output.push_str("\\");
                for _ in 1 .. level {
                    output.push_str("sub");
                }
                output.push_str("section{");
            },
            Event::End(Tag::Header(_)) => output.push_str("}\n"),

            Event::Start(Tag::Emphasis) => output.push_str("\\emph{"),
            Event::End(Tag::Emphasis) => output.push_str("}"),

            Event::Start(Tag::Strong) => output.push_str("\\textbf{"),
            Event::End(Tag::Strong) => output.push_str("}"),

            Event::Start(Tag::List(None)) => output.push_str("\\begin{itemize}\n"),
            Event::End(Tag::List(None)) => output.push_str("\\end{itemize}\n"),

            Event::Start(Tag::List(Some(_))) => output.push_str("\\begin{enumerate}\n"),
            Event::End(Tag::List(Some(_))) => output.push_str("\\end{enumerate}\n"),

            Event::Start(Tag::Link(_, url, _)) => {
                output.push_str("\\href{");
                output.push_str(&*url);
                output.push_str("}{");
            },

            Event::End(Tag::Link(_, _, _)) => {
                output.push_str("}");
            },

            Event::Start(Tag::Image(_, path, title)) => {
                output.push_str("\\begin{figure}\n");
                output.push_str("\\centering\n");
                output.push_str("\\includegraphics[width=\\textwidth]{");
                output.push_str(&*path);
                output.push_str("}\n");
                output.push_str("\\caption{");
                output.push_str(&*title);
                output.push_str("}\n\\end{figure}\n");
            },

            Event::Start(Tag::Item) => output.push_str("\\item "),
            Event::End(Tag::Item) => output.push_str("\n"),

            Event::Start(Tag::CodeBlock(lang)) => {
                if ! lang.is_empty() {
                    output.push_str("\\begin{lstlisting}[language=");
                    output.push_str(&*lang);
                    output.push_str("]\n");
                } else {
                    output.push_str("\\begin{lstlisting}\n");
                }
            },

            Event::End(Tag::CodeBlock(_)) => {
                output.push_str("\n\\end{lstlisting}\n");
            },

            Event::Text(t) => {
                output.push_str(&*t);
            },

            Event::SoftBreak => {
                output.push('\n');
            },

            _ => (),
        }
    }

    output.push_str(LATEX_FOOTER);

    output
}

pub fn markdown_to_pdf(markdown: String) -> Result<Vec<u8>, tectonic::Error> {
    tectonic::latex_to_pdf(markdown_to_latex(markdown))
}