Cannot render custom blocks with cat() - r

As explained in this chapter of the R Markdown Cookbook, it is possible to make custom blocks in R Markdown files with this syntax (here, to center some text):
:::{.center data-latex=""}
Hello
:::
However, using cat() to render this sort of block (as explained in this chapter) does not work.
Full example:
---
output: rmarkdown::pdf_document
---
<!-- WORKS -->
:::{.center data-latex=""}
Hello
:::
<!-- DOES NOT WORK -->
```{r, results='asis', echo=FALSE}
print(
'
:::{.center data-latex=""}\n
Hello\n
:::
'
)
```
Why is the second part not rendering correctly? How to solve that?

There are two issues:
You use print() instead of cat() (even if you refer to cat() in your post
You put spaces at the beginning of each line which prevents the custom block to be rendered.
If you prefer the lines to be indented (as I do) then I would suggest make each line a separate string as I do in the second example. This also has the advantage that you could add the line breaks via the sep argument instead of having to add them manually.
Reproducible example:
---
output:
rmarkdown::pdf_document:
keep_md: true
---
<!-- WORKS -->
:::{.center data-latex=""}
Hello
:::
<!-- WORKS TOO -->
```{r, results='asis', echo=FALSE}
cat('
:::{.center data-latex=""}\n
Hello\n
:::
', sep = "\n"
)
```
<!-- WORKS TOO -->
```{r, results='asis', echo=FALSE}
cat(':::{.center data-latex=""}',
'Hello',
':::', sep = "\n"
)
```

Related

Pass body of Rmarkdown chunk as argument to child document

I've designed an expandable info box for my blog (which is rendered from Rmarkdown) which I want to use as a template.
At the momentan I just write more or less plain HTML in the main Rmarkdown document, as below:
<div class="info" markdown="1">
<details>
<summary class="info-header" markdown="1">
Title <i class="fas fa-info-circle"></i>
</summary>
<p class="info-details">
Here goes the body
</p>
</details>
</div>
With some CSS this renders nicely:
Ideally I would like to replace the HTML above by using some kind of child document which has a title argument to specify the title, and (and this is the tricky part) which passes the whole body of the Rmarkdown chunk to the body section of the child document. So ideally the above HTML could be written as.
```{r, child = "info_box.Rmd", title = "My Title"}
Here goes the body
```
Is this possible? I understand how to insert a child document, also with arguments, and when looking at rmarkdown::hmtl_document() I do get a glimpse of how the use real arguments like title, but can we pass the body of the Rmarkdown chunk down to the child so that it is used at a specific place? Do we need a custom output format for this and how would it look like?
Any help appreciated. I'm also open for other solutions, but it would be more than great if the ideal approach above would work.
I am giving another answer which is based on knitr output hooks and Pandoc Lua filter that also works fine for rmarkdown::html_document (and probably a better approach than the previous one).
Pass the child document path to the chunk option child_into_box and specify the box title to option box_title. One very important detail to note is that you must at least insert a comment in that chunk, otherwise for an empty chunk the redefined knitr source hook does not work.
---
title: Passing Child document Text to Info box.
output:
html_document:
pandoc_args:
- --lua-filter=box_wrap.lua
---
## Rmarkdown
Some text
```{r}
#| echo: false
library(knitr)
default_source_hook <- knit_hooks$get('source')
knit_hooks$set(
source = function(x, options) {
if(is.null(options$child_into_box))
default_source_hook(x, options)
else {
res <- knitr::knit_child(input = options$child_into_box, envir = environment(), quiet = TRUE)
div_start = paste0("::: {wrap-box=true box-title='", options$box_title, "'}")
paste0(div_start, "\n", unlist(res), "\n", "\n:::\n")
}
}
)
```
Some more text
```{r}
#| child_into_box: info_box.Rmd
#| box_title: my info test box
# comment
```
box_wrap.lua
local str = pandoc.utils.stringify
local template_info_box_p1 = [[
<div class="note" markdown="1">
<details>
<summary class="note-header" markdown="1">
%s<i class="fas fa-info-circle"></i>
</summary>
<div class="note-details">
]]
local template_info_box_p2 = [[
</div>
</details>
</div>
]]
function Div(el)
if el.attributes['wrap-box'] then
local title = str(el.attributes['box-title'])
local info_box = string.format(template_info_box_p1, title)
local info_box_rb1 = pandoc.RawBlock('html', info_box)
local info_box_rb2 = pandoc.RawBlock('html', template_info_box_p2)
el.content:insert(1, info_box_rb1)
el.content:insert(info_box_rb2)
return el
end
end
Since the output format is HTML, a possible solution based on pandoc lua filter and Javascript is as follows,
main.Rmd
---
title: Passing Child document Text to Info box.
output:
html_document:
includes:
after_body: infoBox.html
pandoc_args:
- --lua-filter=info_box.lua
---
## Rmarkdown
::: {.info-box title="My new Title" #first}
:::
::: {.add-to-info #first}
```{r}
#| child: info_box.Rmd
```
Also some random text to be inserted into that info box
:::
::: {.info-box title="More info box" #second}
:::
::: {.add-to-info #second}
```{r}
#| child: info_box.Rmd
```
Also some random text to be inserted into that info box
:::
So to add contents from child-document to the info box you need to do two thing.
Firstly, create a pandoc div (using :::) with class .info-box, give it title that you want and give a unique id (suppose, #first) so that we could use it to insert the content of a child document to this specific info box.
secondly, wrap the code chunk with the child option with another pandoc div associated with class .add-to-info and use the id of the info box to where you want the content of this child document to be.
Now following these two steps you can generate as many as info box you want.
info_box.Rmd
Lorem ipsum dolor sit amet, eget, etiam, a metus purus sit quisque elit, suscipit.
```{r}
1 + 1
```
```{r}
plot(1:10)
```
```{r}
head(mtcars)
```
(no need to use title or output for the child document, it simply contains the body text)
info_box.lua
local template_info_box_p1 = [[
<div class="info" markdown="1">
<details>
<summary class="info-header" markdown="1">
%s <i class="fas fa-info-circle"></i>
</summary>
<p class="info-details" id="%s">
]]
local template_info_box_p2 = [[
</p>
</details>
</div>
]]
function Div(el)
if el.classes:includes('info-box') then
local title = el.attributes['title']
local id = el.identifier
local info_box_p1 = string.format(template_info_box_p1, title, id)
local info_box_html_p1 = pandoc.RawBlock('html', info_box_p1)
local child_content = el.content
local info_box_html_p2 = pandoc.RawBlock('html', template_info_box_p2)
return pandoc.Div({info_box_html_p1, info_box_html_p2})
end
end
infoBox.html
<script>
function add_to_info() {
let childs = document.querySelectorAll("div.add-to-info");
let info_box = document.querySelectorAll('p.info-details');
childs.forEach(el => {
info_box.forEach(box => {
if (el.id === box.id) {
box.appendChild(el);
}
});
});
}
window.onload = add_to_info();
</script>
A portion of the rendered ouput
Note that, this output lacks the necessary CSS styles along with fontawesome icon, which you can handle accordingly using the embedded classes info-header and info-details.
I found a first answer looking at this SO post:
I could create a template info_box.Rmd like:
---
title: ""
output: rmarkdown::html_document
---
<div class="note" markdown="1">
<details>
<summary class="note-header" markdown="1">
`r title`<i class="fas fa-info-circle"></i>
</summary>
<p class="note-details">
`r body`
</p>
</details>
</div>
And then replace the intial HTML from my post with:
```{r, echo = FALSE, results='asis'}
title <- "My new Title"
body <- "The new body"
cat(
knitr::knit_child("info_box.Rmd",
envir = environment(),
quiet = TRUE)
)
```
And it works:
However, I'd still prefer a solution looking like this:
```{r, child = "info_box.Rmd", title = "My Title"}
Here goes the body
```

How can I adjust the style of the output from a .Rmd chunk?

Here is an example code chunk and it's output.
`{r example, message = F}
for (i in 1:5) {
print(i)
}
`
I would like this to render in my output file without the border box, and without the leading ## [1]. Is that possible?
This solution also removes the border box.
Use the r chunk comment option to remove the ## character.
Use cat() instead of print() to display the output without the R formatting [1]. You need to specify in cat() that you want newlines added.
One method to remove the border box would be to use css. You can use an external css file, or make a dedicated hidden chunk to specify it.
I noticed the code chunks and output chunks were both specified by the <pre> tag, with the code chunk being of class .r, and the output chunk being .hljs. These might change with different themes, but this selector worked for me. pre.hljs might work alternatively as a selector.
Below is a complete .Rmd file that can be knit to an html document
---
title: example.Rmd
output: html_document
---
```{css, echo = FALSE}
pre:not(.r) {
border: 0px;
}
```
```{r, comment = ""}
for (i in 1:5) {
cat(i, "\n")
}
```
Use the following code
{r example, message = FALSE, comment = ''}
for (i in 1:5) {
cat(i, '\n')
}

R Pagedown resume/cv lowercase letters for title

I am working on creating a resume in R using Pagedown. Currently, the default is to have your name in all capital letters at the top of the first page (e.g. JANE DOE). However, this doesn't look great with my name and I am wondering if there is a way to edit just the title line to have mixed case (Jane Doe). Thanks!
It is possible to remove the uppercase text transformation with CSS like that:
---
title: "Lijia Yu's resume"
author: Lijia Yu
date: "`r Sys.Date()`"
output:
pagedown::html_resume:
# set it to true for a self-contained HTML page but it'll take longer to render
self_contained: false
# uncomment this line to produce HTML and PDF in RStudio:
#knit: pagedown::chrome_print
---
```{css, echo=FALSE}
#title h1 {
text-transform: unset;
}
```
Aside
================================================================================
...

Rmarkdown each chunk on separate pages [duplicate]

I wonder if one could simply use LaTeX \newpage command in R markdown v2 in a different way than this:
```{r, results='asis', echo=FALSE}
cat("\\newpage")
```
I produce pdf_output.
If any1 has any idea please do not hesitate to comment :) !
Thanks
I create pdf like this:
---
title: " "
author: " "
date: "2014"
output:
pdf_document:
includes:
in_header: naglowek.tex
highlight: pygments
toc: true
toc_depth: 3
number_sections: true
keep_tex: true
---
Simply \newpage or \pagebreak will work, e.g.
hello world
\newpage
```{r, echo=FALSE}
1+1
```
\pagebreak
```{r, echo=FALSE}
plot(1:10)
```
This solution assumes you are knitting PDF. For HTML, you can achieve a similar effect by adding a tag <P style="page-break-before: always">. Note that you likely won't see a page break in your browser (HTMLs don't have pages per se), but the printing layout will have it.
In the initialization chunk I define a function
pagebreak <- function() {
if(knitr::is_latex_output())
return("\\newpage")
else
return('<div style="page-break-before: always;" />')
}
In the markdown part where I want to insert a page break, I type
`r pagebreak()`
You can make the pagebreak conditional on knitting to PDF. This worked for me.
```{r, results='asis', eval=(opts_knit$get('rmarkdown.pandoc.to') == 'latex')}
cat('\\pagebreak')
```
If you're having problems with \newpage or \pagebreak and floating figures/tables. You need to use \clearpage, as answered here.

Code chunk font size in Rmarkdown with knitr and latex

In knitr, the size option works fine in a .Rnw file, the following code generates:
\documentclass{article}
\begin{document}
<<chunk1, size="huge">>=
summary(mtcars)
#
\end{document}
However, I can't get it to work in Rmarkdown. The following code does not change the font size, as it did in .rnw file. The same thing happens when trying to set options with opts_chunk$set(size="huge").
Is this the expected behavior? How does one change the chunk code font size? (I mean using knitr options, not by adding \huge before the code)
---
title: "Untitled"
output: pdf_document
---
```{r, size="huge"}
summary(mtcars)
```
I am using RStudio Version 0.98.987, knitr 1.6 and rmarkdown 0.2.68.
Picking up the idea to alter a knitr hook we can do the following:
def.chunk.hook <- knitr::knit_hooks$get("chunk")
knitr::knit_hooks$set(chunk = function(x, options) {
x <- def.chunk.hook(x, options)
ifelse(options$size != "normalsize", paste0("\n \\", options$size,"\n\n", x, "\n\n \\normalsize"), x)
})
This snippet modifies the default chunk hook. It simply checks if the chunk option size is not equal to its default (normalsize) and if so, prepends the value of options$size to the output of the code chunk (including the source!) and appends \\normalsize in order to switch back.
So if you would add size="tiny" to a chunk, then all the output generated by this chunk will be printed that way.
All you have to do is to include this snippet at the beginning of your document.
\tiny
```{r}
summary(mtcars)
```
\normalsize
available options for size in descending order are:
Huge > huge > LARGE > Large > large > normalsize > small > footnotesize > scriptsize > tiny
Per this Gist, you have to define the font size using css:
<style type="text/css">
body, td {
font-size: 14px;
}
code.r{
font-size: 20px;
}
pre {
font-size: 20px
}
</style>
code.r will control the font size for R code echoed from the code chunk, while pre will apply to any R results output from the code.
A complete working .Rmd file might look like:
---
title: "FontTest"
author: "Thomas Hopper"
date: "January 13,2016"
output: html_document
---
<style type="text/css">
body, td {
font-size: 14px;
}
code.r{
font-size: 20px;
}
pre {
font-size: 20px
}
</style>
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
The resulting html renders as:
You can define you own document format by exporting something based on the following function from your package my_package:
my_report <- function(...) {
fmt <- rmarkdown::pdf_document(...)
fmt$knitr$knit_hooks$size = function(before, options, envir) {
if (before) return(paste0("\n \\", options$size, "\n\n"))
else return("\n\n \\normalsize \n")
}
return(fmt)
}
This will define a knitr chunk hook size that will put the appropriate latex command before the chunk, and \normalsize after the chunk.
Anyway, with the following R markdown you can check if it's working:
---
output: my_package::my_report
---
Test text for comparison
```{r}
print(1)
```
The next code chunk has `size = 'tiny'` in the chunk options.
```{r, size = 'tiny'}
print(1)
```
I get the following result from `markdown::render():
See also the issue I opened on github:
https://github.com/yihui/knitr/issues/1296
Following up on #Martin Schmelzer's output, here's a solution in the case you want to change the code and output default font size for the whole document, but not the size of the text.
def.chunk.hook <- knitr::knit_hooks$get("chunk")
knitr::knit_hooks$set(chunk = function(x, options) {
x <- def.chunk.hook(x, options)
paste0("\n \\", "size_of_the_code_and_output","\n\n", x, "\n\n \\size_of_the_text")
})
For instance,
---
output: pdf_document
---
```{r setup, include=FALSE}
def.chunk.hook <- knitr::knit_hooks$get("chunk")
knitr::knit_hooks$set(chunk = function(x, options) {
x <- def.chunk.hook(x, options)
paste0("\n \\", "footnotesize","\n\n", x, "\n\n \\Huge")
})
```
# Section 1
```{r}
summary(cars)
```
Text.
# Section 2
```{r}
print(1)
```
This works for every chunks.
gives this:

Resources