How Can I Prevent R Markdown From Escaping Characters in Custom Blocks

Let's say I want to recreate this LaTeX code into a custom block:

\begin{tabularx}{\linewidth}{p{0.5\linewidth} X}
\toprule
Column 1 & Column 2 \\
\midrule
\textbf{Lorem} & Ipsum \\
\bottomrule
\end{tabularx}

I tried to do this:

::: {.tabularx data-latex="{\linewidth}{p{0.5\linewidth} X}"}
\toprule
Column 1 & Column2 \\
\midrule
**Lorem** & Ipsum \\
\bottomrule
:::

But it automatically escapes all of the & and \\. Here is the LaTeX output:

\begin{tabularx}{\linewidth}{p{0.5\linewidth} X}
Column 1 \& Column2 \textbackslash{}
\midrule
\textbf{Lorem} \& Ipsum \textbackslash{}
\bottomrule
\end{tabularx}

How do I prevent them from being escaped? The main reason I want to do this is I've been in a situation where I want to use Markdown syntax in a LaTeX table but there's no good R package for creating that LaTeX table.

You are writing here some Markdown syntax. So Pandoc will convert anything as Markdow to LaTeX, unless you tell Pandoc not to do it. Or you need to write raw latex and mark the block as raw latex

Several solutions

::: {.tabularx latex="{\\linewidth}{p{0.5\\linewidth} X}"}
\toprule\
Column 1 & Column2\
\midrule\
**Lorem** & Ipsum\
\bottomrule\
:::
  • Write raw latex using ```{=latex} block
::: {.tabularx latex="{\\linewidth}{p{0.5\\linewidth} X}"}
```{=latex}
\toprule
Column 1 & Column2\\
\midrule
\textbf{Lorem} & Ipsum\\
\bottomrule
```
:::

or even using no custom block

So in conclusion, either you write raw LateX or you write Markdown syntax that would be transformed to LaTeX. Mixing both does not always work well.

This is almost a perfect solution but there is one problem: the & is still escaped. I don't know if there is a way to prevent it from being escaped.

That's what I did as a workaround, but I prefer not to do this because I want to use markdown syntax in the table. For example, if I want to cite a source [@source], it will not work in the LaTeX block.

If I cannot properly make a table in a custom block, I will probably fork kable from the knitr package and make my own table package.

Just look are documentation: we mentioned several time that writing Markdown requires escaping sometimes depending on your output. If you don't want a & but a special LaTeX character you need to escape:

So just use \& instead of & if you don't want it to be considered as Markdown.

Markdown in LaTeX tables is not something that is supported by Pandoc yet (A markdown_in_tex_blocks extension · Issue #2453 · jgm/pandoc · GitHub) that is why mixing both even in table package does not always works. Outputing a Markdown Table with knitr will work though. What does not work for you with this ?

Other table packages like gt or flextable are also to consider.

1 Like

Using \& instead of & doesn't fix it. The all_symbols_escapable Markdown extension unfortunately doesn't either. For now, I will continue to use =latex code chunks. None of the table packages listed in the R Markdown Cookbook do what I want.

About this, I misunderstood as you did not shared what results you had. I though the & was converted to something else.

I believe the & is escaped as it is seen as raw Markdown, then converted to LaTeX and I believe & in LaTeX needs to be escaped, unless in table environment maybe ?
It seems Pandoc will at least escape it because not in a LaTeX block. Pandoc is doing the conversion from & to \&. If you use raw LaTeX in the markdown though, it will keep it as is

\begin{tabularx}{\linewidth}{p{0.5\linewidth} X}
\toprule
Column 1 & Column 2 \\
\midrule
\textbf{Lorem} & Ipsum \\
\bottomrule
\end{tabularx}

without escaping.

As I said, it is a limitation of Pandoc : Markdown syntax can't be mixed within a LaTeX block.

This would be interesting to share what you are looking for. R offers a lot of table framework and it would be interesting for them to know that you have a use case not handled by them.

I don't know what is missing really from what you described, but maybe there is a way you did not find. kable() can take table.envir argument among other to customise the LaTeX written. xtable has a tabular.envir and example in its doc with tabularx.

I am sorry I can't help more. I believe you are encountering the limitation mentioned above. If you can't use a R package for that, you need to write Markdown Table or Raw LaTeX directly in a way that Pandoc can convert them correctly.

I think my table is too complex to be able to make it in any available R package. Here is an example of a table I would make:

\begin{xltabular}{\linewidth}{p{0.1\linewidth} Y Y Y Y Y Y}
\toprule
Activity & \multicolumn{2}{l}{February 10, 2022} & \multicolumn{2}{l}{April 26, 2022} & \multicolumn{2}{l}{June 6, 2022}\\
\cmidrule(lr){2-3}
\cmidrule(lr){4-5}
\cmidrule(l){6-7}
& Score & Goal & Score & Goal & Score & Goal\\
\midrule\endfirsthead
\toprule
Activity & \multicolumn{2}{l}{February 10, 2022} & \multicolumn{2}{l}{April 26, 2022} & \multicolumn{2}{l}{June 6, 2022}\\
\midrule\endhead
Push-ups & 20\newline Level 1 & 25\newline Level 2 & 29\newline Level 2 & 40\newline Level 4 & 30\newline Level 3 & 40\newline Level 4\\
\addlinespace
Crunches & 24\newline Level 1 & 30\newline Level 2 & 40\newline Level 2 & 30\newline Level 3 & 26\newline Level 3 & 40\newline Level 3\\
\addlinespace
Plank & 1:00\newline Level 1 & 1:30\newline Level 1 & 1:13\newline Level 1 & 1:30\newline Level 2 & 2:01\newline Level 3 & 3:00\newline Level 3\\
\addlinespace
Vertical jump & 40 & 50 & 36 & 50 & 40 & 50\\
\addlinespace
Sit, reach, and hold & 16 & 17 & 16 & 17 & 17 & 18\\
\bottomrule
\end{xltabular}

Here is the output:

Here are the things making it seem impossible to make this table in kable:

  1. The table.envir argument replaces the table environment instead of the tabular environment. I do not want my table to be in a floating table environment. I want it to be in xltabular alone.
  2. It will not work with the xltabular or tabularx environment because they expect two arguments, as opposed to tabular which just expects one argument.
  3. I'm not sure how to add cmidrules in any R package. In LaTeX it's \cmidrule.
  4. I want \addlinespace to be added between every column.

Yes it is possibly. You should included it in your document using Raw LaTeX then with

```{=latex}
<your table in LaTeX>
```

this way it will be preserved during Pandoc conversion.

Doing complex table in LaTeX without writing LaTeX directly is not that easy so it makes sense that you don't find what you want. gt or flextable can do complex layout, but not great (yet) for LaTeX unfortunately (unless shared in LaTeX as image not table probably).

Yeah, right now I just use the =latex code chunk. If I wanted to make my own R package for tables, is it better to start from scratch or fork kable from knitr?

You cannot just fork kable, you would need to fork knitr which is a bit too much.
you could definitely take inspiration from kable() and other package. Also, take care of the Licence when forking a piece of code : knitr is GPL for example:

One scenario is also submitting a PR to one of the existing package so that your use case is better supported. Maybe better than to start from scratch ?

By the way a few answer I found

This should probably be improved in kable() to allow modifying tabular environment ? You can submit a feature request or a PR.

Probably the same ?

This is definitely not supported currently in kable() and would require adding such feature

linesep in knitr::kable() allows to add \addlinespace

huxtable is another package that has complex table support - don't know for sure what is really supported or not. Looking at the code could help.

And I see you got it working `\addlinespace` is not added in `kable(booktabs = TRUE)` · Issue #2133 · yihui/knitr · GitHub

You're right. kable is almost perfect for me except for a few things that are missing. Should I create a fork on GitHub and submit a PR?

I will add a feature request or a PR.

As for tabularx and xltabular, this can probably be fixed by adding an option called tabularx or something like that to create a table like this:

\begin{tabularx}{\linewidth}{X X X}
\end{tabularx}

instead of like this:

\begin{tabular}{lll}
\end{tabular}

For tabularx, the first argument is for the length of the table. The second argument is for the alignment or the length of each column. X X X for three columns means it will divide the three columns evenly (1/3 each). This should be the default. I think there should be an argument to change this too.

Yeah, there should be an argument to put cmidrules.

I will submit pull requests if I can. If I cannot, I will do feature requests instead. Thank you.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.