2
votes

How can I make it possible that markdown code used inside Latex Code gets evaluated? (Rmarkdown with PDF (Latex) Output)

Very simple minimal example:

\begin{center}
**should be bold text**
\end{center}

Current output in .tex file after compiling with knitr:

\begin{center}
**should be bold text**
\end{center}

Expected:

\begin{center}
\textbf{should be bold text}
\end{center}

I would be happy to find a way to get this working, because I try to find a way in which I can pass a tibble/dataframe through kable/kableExtra. Table cells can already contain Latex code, but no markdown code, since kable converts everything into a Latex structure.

It seems to me like all Markdown code inside any Latex code block doesn't get evaluated.

I know that I can achieve the same result by just using Latex Code, but I prefer using the Markdown shortcuts wherever possible.

Edit:

@duckmayr kindly offered to review another minimal example to see how it's possible to automatically change Latex code produced by R functions in order to make it work (together with the proposed & accepted answer, thx). So I'm looking for some kind of wrapper that would work regardless what R function I use (here: one basic R example and a simple kable test; could also be Stargazer, or something)

---
title: "Untitled"
output: 
  pdf_document:
    keep_tex: true
    df_print: kable
header-includes:
    - \let\Begin\begin
    - \let\End\end
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, results='hide', message=FALSE, warning=FALSE)
library(kableExtra)
```


```{r test1, results='asis'}
test = function(x=1){
  cat('\\begin{center}\n**test**\n\\end{center}')
}
test()
```

```{r test2, results='asis'}
kable(data.frame(x=c("**bold text**")),"latex")
```
2

2 Answers

3
votes

Someone opened an issue on the pandoc GitHub repo about this a couple years ago, and we can find there a workaround: Making LaTeX synonyms for \begin{} and \end{}. So, to use this in R Markdown, we just put them in header-includes:

---
title: "Stack Overflow Answer"
author: "duckmayr"
date: "5/9/2020"
output:
    pdf_document:
        keep_tex: true
header-includes:
    - \let\Begin\begin
    - \let\End\end
---

\Begin{center}

**should be bold text**

\End{center}

LaTeX output:

... Many initial lines skipped ...
\let\Begin\begin
\let\End\end

\title{Stack Overflow Answer}
\author{duckmayr}
\date{5/9/2020}

\begin{document}
\maketitle

\begin{center}

\textbf{should be bold text}

\end{center}

\end{document}

PDF output:

enter image description here

Update: What about using things like kable()?

To deal with using things like kable() in R chunks with results='asis', we'll need to fix the output of kable(); namely, we'll need to change its \begin{} and \end{} tags to \Begin{} and \End{}, and we'll also need to make sure we don't end up converting \\ sequences to textbackslash{}s. Here's how we'd do that:

---
title: "Untitled"
output: 
  pdf_document:
    keep_tex: true
    df_print: kable
header-includes:
    - \let\Begin\begin
    - \let\End\end
    - \newcommand{\Newrow}{\\}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, results='hide', message=FALSE, warning=FALSE)
library(kableExtra)
allow_markdown <- function(tex) {
    tex <- gsub("begin", "Begin", tex) ## fix \begin{} tags
    tex <- gsub("\\\\end", "\n\\\\End", tex) ## fix \end{} tags
    tex <- gsub("\\\\\\\\", "\\\\Newrow\n", tex) ## fix new row \\
    return(tex)
}
```

```{r test2, results='asis'}
kable(data.frame(x=c("**bold text**")),"latex")
```

```{r test3, results='asis'}
allow_markdown(kable(data.frame(x=c("**bold text**")), "latex"))
```

We added a new LaTeX command in the header with \newcommand{\Newrow}{\\} so that we can safely add \\ without them being converted to \textbackslash{}. This is necessary because of how we're tricking pandoc into processing the markdown in the environment between \Begin and \End.

We also added an R function for fixing up the LaTeX output of kable() that fixes the begin and end tags and the new row \\ characters.

Then we get the following LaTeX and PDF output:

[header omitted]
\begin{document}
\maketitle

\begin{tabular}{l}
\hline
x\\
\hline
**bold text**\\
\hline
\end{tabular}

\begin{tabular}{l}
\hline

x\\

\hline

\textbf{bold text}\\

\hline

\end{tabular}

\end{document}

enter image description here

1
votes

If you only need a simple LaTeX environment, I'd recommend that you use fenced Div blocks in Pandoc's Markdown (see this section in the R Markdown Cookbook for more info), e.g.,

::: {.center}
**should be bold text**

```{r}
knitr::kable(head(iris))
```
:::

In the fenced Div block, you can write arbitrary Markdown content. Besides, this also works for HTML output.

Note that this feature requires a relatively new version of Pandoc, and the development version of rmarkdown. You may try the RStudio Preview version (if you use RStudio), together with remotes::install_github('rstudio/rmarkdown').