Change default behavior of callout blocks in Quarto - r-markdown

In Quarto, I'd like to change the default behavior of a single callout block type so that it will
always automatically have the same caption (e.g. "Additional Resources")
always be folded (collapse="true")
Let's say I want this for the tip callout block type while the others (note, warning, caution, and important) should not be affected.
In other words, I want the behavior/output of this:
:::{.callout-tip collapse="true"}
## Additional Resources
- Resource 1
- Resource 2
:::
by only having to write this:
:::{.callout-tip}
- Resource 1
- Resource 2
:::

Update:
I have actually converted the following lua filter into a quarto filter extension collapse-callout, which allows specifying default options for specific callout blocks more easily. See the github readme for detailed instructions on installation and usage.
As #stefan mentioned, you can use pandoc Lua filter to do this more neatly.
quarto_doc.qmd
---
title: "Callout Tip"
format: html
filters:
- custom-callout.lua
---
## Resources
:::{.custom-callout-tip}
- Resource 1
- Resource 2
:::
## More Resources
:::{.custom-callout-tip}
- Resource 3
- Resource 4
:::
custom-callout.lua
local h2 = pandoc.Header(2, "Additional Resources")
function Div(el)
if quarto.doc.isFormat("html") then
if el.classes:includes('custom-callout-tip') then
local content = el.content
table.insert(content, 1, h2)
return pandoc.Div(
content,
{class="callout-tip", collapse='true'}
)
end
end
end
Just make sure that quarto_doc.qmd and custom-callout.lua files are in the same directory (i.e. folder).

After a look at the docs and based on my experience with customizing Rmarkdown I would guess that this requires to create a custom template and/or the use of pandoc Lua filters.
A more lightweight approach I used in the past would be to use a small custom function to add the code for your custom callout block to your Rmd or Qmd. One drawback is that this requires a code chunk. However, to make your life a bit easier you could e.g. create a RStudio snippet to add a code chunk template to your document.
---
title: "Custom Callout"
format: html
---
```{r}
my_call_out <- function(...) {
cat(":::{.callout-tip collapse='true'}\n")
cat("## Additional Resources\n")
cat(paste0("- ", ..., collapse = "\n\n"))
cat("\n:::\n")
}
```
```{r results="asis"}
my_call_out(paste("Resource", 1:2))
```
Blah blah
```{r results="asis"}
my_call_out("Resource 3", "Resource 4")
```
Blah blah

Related

Quarto: .content-visible div dependent on params?

Using quarto, I'd like to do something like:
---
params:
show_private_info: true
---
::: {.content-visible <ARGUMENT TESTING FOR `params$show_private_info`>}
Some private information
:::
Is that feasible?
Clearly something can be whipped up using an asis (r) code block cating out the markdown, with eval dependent on params$show_private_info, but I'd like to avoid that detour if possible ...
Answered here as follows:
`r if (params$show_private_info) "::: {.content-hidden}"`
Some private information
`r if (params$show_private_info) ":::"`
with the additional recommendation to explicitly solve this by use of actual profiles instead.

Difference in PDFs when manually generated with Knit-Button vs rmarkdown::render() - e.g. section numbers not always included

I try to generate multiple reports (1 per group) with rmarkdown::render(), but it produces no section numbers.
I use the following file-structure for this in case you want to reproduce the sample (I tried to simplify each file and use only necessary code to reproduce the error):
*) groups.R: defines groups and subgroups in a nested list (all groups stored in a list and each group is a list itself)
groups <- list(
list(c("subgroup1","subgroup2"),"maingroup1"),
list(c("subgroup3","subgroup4"),"maingroup2")
)
*) main.Rmd: template for the reports
---
output:
pdf_document:
number_sections: true
classoption: a4paper
geometry: left=2cm,right=1cm,top=1.5cm,bottom=1cm,includeheadfoot
fontfamily: helvet
fontsize: 11pt
lang: en
header-includes:
- \usepackage{lastpage}
- \usepackage{fancyhdr}
- \pagestyle{fancy}
- \fancyhf{}
- \fancyhead[R]{\fontsize{9}{11} \selectfont \leftmark}
- \fancyhead[L]{\fontsize{9}{11} \selectfont Special report xxx}
- \fancyfoot[R]{\fontsize{9}{0} \selectfont Page \thepage\ of
\pageref{LastPage}}
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(echo =
FALSE,comment=NA,warning=FALSE,message=FALSE)
```
\thispagestyle{empty}
\tableofcontents
\newpage
\setcounter{page}{1}
# Introduction
Some text...
```{r results="asis"}
source("graphics.R")
```
*) graphics.R: generates graphics for each subgroup (sections/section numbers are produced with cat() for each subgroup)
load("actgroup.RData")
source("template_graphics.R")
for (g in 1:length(act.group[[1]][[1]])) {
subgroup.name <- act.group[[1]][[1]][g]
cat("\\clearpage")
cat("\n# ",subgroup.name, "\n")
template_graphics(cars)
cat("\n\n")
cat("\\clearpage")
template_graphics(iris)
cat("\n\n")
cat("\\clearpage")
template_graphics(airquality)
cat("\n\n")
cat("\\clearpage")
cat("\n")
}
*) template_graphics.R: template for plotting
template_graphics <- function(data) {
plot(data)
}
*) loop.R: used for generating all reports as PDF - 1 per group
setwd("YOUR DIRECTORY HERE")
library(rmarkdown)
source("groups.R")
for(i in 1:length(groups)) {
act.group = list(groups[[i]])
save(act.group,file="actgroup.RData")
rmarkdown::render("main.Rmd",
output_format=pdf_document(),
output_file=paste0("Special Report ",act.group[[1]][[2]],".pdf"),
output_dir="~/Reports")
}
The problem is, that the final documents do not show the section numbers. When I knit manually in main.Rmd (pressing knit-Button), the section numbers are printed.
Version rmarkdown::render
Version knit-Button
I thought that pressing the knit-Button also starts the rendering-process with rmarkdown::render()? So it's surprising that the reports are not identical?
In advance I installed tinytex::install_tinytex(). The used latex-packages in main.Rmd were automatically installed during the first time rendering.
I am not sure what the problem is. I use R 4.1.0 and RStudio 2022.02.2.
Thanks for your help!!
The behaviour of pdf_document() as the output-format in rmarkdown::render caused the missing section-numbers.
In my YAML-header in main.Rmd I chose to keep the section numbers with number_sections: true. If this should also be rendered when using rmarkdown::render, it has to be an argument in the function:
pdf_document(number_sections=TRUE)
The code of loop.R produces now pdfs with section numbers:
library(rmarkdown)
source("groups.R")
for(i in 1:length(groups)) {
act.group = list(groups[[i]])
save(act.group,file="actgroup.RData")
rmarkdown::render("main.Rmd",
output_format=pdf_document(number_sections=TRUE),
output_file=paste0("Special Report ",act.group[[1]][[2]],".pdf"),
output_dir="~/Reports")
}
More information on pdf_document() can be found here:
https://pkgs.rstudio.com/rmarkdown/reference/pdf_document.html
Alternatively, fill in just a text-reference as output-format: output_format="pdf_document". When set like this, the options of the YAML-Header are not overwritten and the numbers are also included.

Embed XML from file into RMD

I have an XML file (SOME.XML), the contents of which I would like to embed in an .RMD document.
If I was content with having the XML reside directly within the .RMD, I'm aware that I could simply do:
```xml
---some xml here---
```
My embarassing attempts so far are:
```{xml code=readr::read_file('SOME.XML')}
```
...which failed as there is no XML engine.
I have also tried:
````{r results='asis'}
cat('```xml')
cat(readr::read_file('SOME.XML'))
cat('```')
````
...for which, although the knitting completes, the output is not at all correct.
Is this possible? (No doubt there is some trick here that I am missing!)
If needed, I could have a pre-knit stage where the content of the XML file is substituted in before subsequently passing a modified version of the .RMD to rmarkdown::render. However, I'd like to avoid this if possible.
Update:
Using readLines as proposed by the answer is complaining about ...incomplete final line found on 'SOME.XML'. Using readr::read_file() avoids this for me. For my particular project, I am now using:
```xml
`r readr::read_file("SOME.XML")`
```
Thank you to #user2554330 for the elegant solution!
Here's one way to do it:
```xml
`r paste(readLines("SOME.XML"), collapse = "\n")`
```
The idea is to put the XML into inline R code. I think knitr ignores the chunk wrappers because they aren't in the {xml ... format it looks for, but it will see the inline code and expand it. Then Pandoc will handle the formatting.
Here's how to modify your approach to get it to work:
````{r results='asis', echo = FALSE}
cat('```xml\n')
cat(readr::read_file('SOME.XML'), sep = "\n")
cat('\n```\n')
````

bibtext references not processing in bookdown

I have a bookdown document that cites other documents using a bibtex bibliography file. It appears to no process at all, since the output (both gitbook format and pdf) don't translate the actual citation to a reference. The output always copies the plain text of the citation, not the actual reference, like this:
Here's a minimal reproducing example, which I build using:
Rscript -e 'bookdown::render_book("index.Rmd", "bookdown::gitbook")'
index.Rmd:
---
title: "test"
site: "bookdown::bookdown_site"
documentclass: book
bibliography: test.bib
biblio-style: apalike
link-citations: true
# toc: yes
# toc_depth: 2
---
# Introduction {#ch:intro}
Conference publication takes the lead role in describing innovative research,
while journals are often delegated to archival purposes [#vrettas15:conferences].
```{r echo=FALSE}
sessionInfo()
```
test:bib:
#article{vrettas15:conferences,
title = {Conferences versus journals in computer science},
author = {Vrettas, George and Sanderson, Mark},
journal = {Journal of the Association for Information Science and Technology},
volume = 66,
number = 12,
pages = {2674--2684},
year = 2015,
publisher = {Wiley Online Library}
}
_bookdown.yml:
rmd_files: [
"index.Rmd",
]
new_session: no
bookdown::gitbook:
split_bib: no
It turns out to be due to the too low version of Pandoc. A version 1.19.x or higher should fix the problem.

break a slide of reveal.js (xaringan) when it's long

I'm actually using xaringan, but it uses reveal.js, so it should be the same.
I have a slide which prints bibliography using RefManageR, and I'd like to use as many slides as needed:
---
```
{r results = "asis", echo = FALSE}
PrintBibliography(bib, .opts = list(check.entries = FALSE, sorting = "ynt"))
```
---
I guess I'm looking for some type of allowframebreaks, but I couldn't manage to find one.
Xaringan uses remark.js, not reveal.