Wrapping plots in another html container within an Rmd file - r

I have a situation where, for display purposes, I need to wrap an outputted plot in a <div> container.
At the most basic level, this is what I would like to do:
```{r fig.width=7, fig.height=6,results='asis',echo=FALSE}
cat('<div>')
plot(cars)
cat('</div>')
```
However, the output document looks like this:
![plot of chunk unnamed-chunk-2](figure/unnamed-chunk-2.png)
Is there a workaround if you need to "wrap" output?
The same behaviour only seems to occur when it's wrapping the plot. Otherwise, including closed tags works as expected:
```{r fig.width=7, fig.height=6,results='asis',echo=FALSE}
cat('<div>')
cat('</div>')
plot(cars)
cat('<h1>Hello</h1>')
```
Yet wrapping the image seems to break it. I'm also noticing that <img> is wrapped in <p> is it possible to stop this behaviour?

Here is one way to do it.
First, we create a chunk hook to wrap chunk output inside a tag.
We pass wrap = div as chunk option to wrap inside div.
Set out.extra = "" to fool knitr into outputting html for plot output. Note that this is required only for div tag and not for span, as markdown is parsed inside span tag.s
DONE!
Here is a gist with Rmd, md and html files, and here is the html preview
## knitr Chunk Hook to Wrap
```{r setup, echo = F}
knit_hooks$set(wrap = function(before, options, envir){
if (before){
paste0('<', options$wrap, '>')
} else {
paste0('</', options$wrap, '>')
}
})
```
```{r comment = NA, echo = F, wrap = 'div', out.extra=""}
plot(mtcars$mpg, mtcars$wt)
```

Related

Highlight text inline. R-markdown with reference .docx

I need to be able to highlight all text in an r-markdown document that has been inserted using an inline code chunk. E.G r TEXT.
This is to enable editing of the automated Word document creation.
I have tried using
.highlight {
background-color: lightpink;
border: 3px solid red;
font-weight: bold;
}
r sprintf("<span class='highlight'>%s</span>",PNAME)
AND
r text_spec(TEXT, color = "red")
However, I suspect these are not working due to the reference .docx that I am using over-riding the styles.
Is there a way to still use the reference doc and have the highlighting??
Thanks in advance.
Silas
Using officedown::rdocx_document: default as the output type, we can use ftext and fp_text function from {officer} package to highlight text that were inserted using inline r code chunk.
---
title: "Inline code styling"
output:
officedown::rdocx_document: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(officer)
ft <- officer::fp_text(shading.color = "yellow")
word_spec <- function(x, prop = ft) ftext(text = toString(x) ,prop = ft)
```
## Inline code highlighting for word document
We can highlight text in an r-markdown document that has been inserted using an inline code for output type word document too.
- `r word_spec("text in inline code is highlighted")`
- The sum of 2 + 2 is `r word_spec(2 + 2)`
- The sequence from 1 to 10 is `r word_spec(1:10)`
And the rendered word document looks like this,

CSS selector for font color in flextable with shadow host on

I'm unsuccessfully trying to set the font color for flextable generated in r markdown using a css stylesheet.
I can accomplish this when I turn off shadow host, but not with it on. (Just turning it off removes other desirable features.) Here's a short r markdown file demonstrating the difference.
---
title: "Untitled"
output: html_document
---
<style>
div.flextable-shadow-host * {
color: pink;
}
div.tabwid * {
color: pink;
}
</style>
# ignores CSS above
```{r, echo=FALSE}
library(flextable)
flextable(head(mtcars))
```
# accepts CSS above
```{r, echo=FALSE}
ft <- flextable(head(mtcars))
htmltools_value(ft, ft.shadow = FALSE)
```
I want the css external to the r code because I have a button selector on the website the user can change the overall style (e.g., dark mode or not).
When using shadow, the table is assembled outside of HTML. Only the id connects the table to HTML. However, flextable has functions for setting the color. Why not just use one of the many built-in methods to change the color?
For example:
# ignores CSS above
```{r liberator,include=F}
library(flextable)
library(tidyverse)
```
```{r tbler, echo=FALSE}
flextable(head(mtcars)) %>%
color(color = "pink", part = "all")
```
# accepts CSS above
```{r, echo=FALSE}
ft <- flextable(head(mtcars))
htmltools_value(ft, ft.shadow = FALSE)
```
There are many things you can do with flextable styling. You can see more customization options here.
Update: Based on your comments
Okay, this works to change the color of a flextable.
This works if there is only one flextable in the script.
I have the color of the text set to #b21E29 (a shade of red). You can change that as you see fit.
These will SKIP non-shadow flextables
Add this chunk anywhere in your RMD script. This requires no additional libraries or any other customization in your R code.
```{r js_ing,results="asis",engine="js",echo=F}
// extract the styles that are set for the flextable
letMe = document.querySelector('div.flextable-shadow-host').shadowRoot.querySelector('div>style');
// replace color style
// preceding ';' so that 'background-color' doesn't change
letMe.innerHTML = letMe.innerHTML.replace(/;(color:.+?);/g, ';color:#b21e29 !important;');
```
If you have more than one flextable with shadow on, you can use one of the two following chunks instead. In the first--all the same color; in the second--each table has a different color.
These work if there is more than one flextable in the script.
Pay attention to the comments so you can see what to use when depending on your desired output.
All the same color:
```{r moreJs_ing,results="asis",engine="js",echo=F}
// collect all of the flextables with shadow
letMe = document.querySelectorAll('div.flextable-shadow-host');
// to set all shadow flextables to the same font color:
for(i = 0, n = letMe.length; i < n; i++){
showMe = letMe[i].shadowRoot.querySelector('div>style');
showMe.innerHTML = showMe.innerHTML.replace(/;(color:.+?);/g, ';color:#b21e29 !important;');
}
```
Each with there own color:
```{r evenMoreJs_ing,results="asis",engine="js",echo=F}
//alternatively to set each to a different color
// make sure you only include one of these options!
// collect all of the flextables with shadow
letMe = document.querySelectorAll('div.flextable-shadow-host');
// first table in script
showFirst = letMe[0].shadowRoot.querySelector('div>style');
showFirst.innerHTML = showFirst.innerHTML.replace(/;(color:.+?);/g, ';color:#b21e29 !important;');
// second table in script
showSecond = letMe[1].shadowRoot.querySelector('div>style');
showSecond.innerHTML = showSecond.innerHTML.replace(/;(color:.+?);/g, ';color:#003b70 !important;');
// change the indices for each table, keep in mind the first table is [0], not [1]
```
If you aren't sure where you want to go with these, add all three and and include=F as a chunk option to the two you aren't using at that moment in time.

Custom CSS to rmarkdown chunk to change width of graph

I have an rmarkdown document which output html. I have my own css styles that I use by adding it to the YAML header. I also want to control css of specific code chunks. I have a dashboard (3x2 grid of plots) that I want to have larger width than the main document.
I've found these two questions:
Add a CSS class to single code chunks in RMarkdown
Adding custom CSS tags to an RMarkdown html document
But neither of them are working for me (or I didn't understand the answers). I want to change the width of a plot so it float into the margins e.g. width: 110%. I tried this:
```{r dash1, fig.height=16, fig.width=14, results="asis"}
cat("
<style>
.toc-content {
width: 110%;
}
</style>
")
margin = theme(plot.margin = unit(c(1,2,1,2), "cm"))
pl_1 <- list(g_1_kaupmattur, g_2_gallup, g_3_vnv, g_4_spa, g_5_ibud, g_6_swirlo)
grid.arrange(grobs = lapply(pl_1, "+", margin), ncol = 2)
```
This changed the whole document, not only the output of this particular chunk.
I also tried creating a new css style with width: 110% and adding it to the chunk option like this:
```{r dash1, fig.height=16, fig.width=14, class.source="dash_styles"}
margin = theme(plot.margin = unit(c(1,2,1,2), "cm"))
pl_1 <- list(g_1_kaupmattur, g_2_gallup, g_3_vnv, g_4_spa, g_5_ibud, g_6_swirlo)
grid.arrange(grobs = lapply(pl_1, "+", margin), ncol = 2)
```
It didn't work either.
I would like the plot to extend to the margins as I "show" on the screenshot below.

Can I align body text with margin note?

I'm using the tufte R package to create an html document with margin notes. Some of my margin notes are figures that are fairly tall. For example:
---
title: Big sidenote
output:
tufte::tufte_html: default
---
```{r setup, include=FALSE}
library(tufte)
# invalidate cache when the tufte version changes
knitr::opts_chunk$set(tidy = FALSE, cache.extra = packageVersion('tufte'))
options(htmltools.dir.version = FALSE)
```
```{r fig.margin = TRUE, fig.cap="Fig1. My margin figure is kind of tall.", echo=FALSE}
plot(mtcars)
```
Here is paragraph 1. It's pretty short and it's associated with Fig 1.
```{r fig.margin = TRUE, fig.cap="Fig 2. Related to the second paragraph.", echo=FALSE}
plot(subset(mtcars, cyl==6))
```
I'd like this paragraph to start in line with Fig 2.
```
I would like the paragraph in the main body to begin below the bottom of the figure in the margin.
Is this possible within the markdown? My CSS skills/understanding are limited.
I figured this out. Simple for those who know CSS well, but here for those who don't. The margin notes are created with a float property. You can use the float property to disallow floating elements to the side of your text.
I created a new "cleared" class that clears elements to the right:
<style>
.cleared {clear: right;}
</style>
Then, whenever I wanted text to skip down to the next figure, I created a div of the cleared class:
<div class = "cleared"></div>
Here is the full example:
---
title: Big sidenote
output:
tufte::tufte_html: default
---
<style>
.cleared {clear: right;}
</style>
```{r setup, include=FALSE}
library(tufte)
# invalidate cache when the tufte version changes
knitr::opts_chunk$set(tidy = FALSE, cache.extra = packageVersion('tufte'))
options(htmltools.dir.version = FALSE)
```
```{r fig.margin = TRUE, fig.cap="Fig1. My margin figure is kind of tall.", echo=FALSE}
plot(mtcars)
```
Here is paragraph 1. It's pretty short and it's associated with Fig 1.
<div class = "cleared"></div>
```{r fig.margin = TRUE, fig.cap="Fig 2. Related to the second paragraph.", echo=FALSE}
plot(subset(mtcars, cyl==6))
```
I'd like this paragraph to start in line with Fig 2.
And the result:

How to: A scenebreak in bookdown

I'm trying to write a novel using bookdown: HTML, EPUB, as well as PDF (pdfLaTeX). I'm using the indent mode, so paragraphs begin with an indent. I have the following custom LaTeX command, called \scenebreak, which:
Leaves an empty line between paragraphs when the scene changes within a chapter.
Introduces a ding, if the scene break is at the end of a page, or the beginning of a page.
Resets indent for the paragraph that follows the break (the paragraph that follows the break starts flush left).
Here's the LaTeX:
% scene breaks
\renewcommand{\pfbreakdisplay}{%
\scriptsize\ding{86}}
\newcommand{\scenebreak}{\pfbreak*\noindent}
\newcommand{\forceindent}{\leavevmode{\indent}}
When introducing the scenebreak in LaTeX, I call it so
Text here
\scenebreak
New scene begins here.
In HTML, this is how I've done it:
<div style='text-align:center;'>•</div>
I'm aware that a block in bookdown is like a LaTeX environment.
Is a similar setup possible with commands/macros?
I don't really understand your question, but if you are trying to write out different content depending on the different output format, here is what you could do:
```{r echo=FALSE}
knitr::asis_output(if (knitr:::is_latex_output()) {
"\\scenebreak"
} else {
"<div style='text-align:center;'>•</div>"
})
```
If you have to do this multiple times, create a function and call the function instead, e.g., insert this code chunk in the beginning of your book:
```{r, include=FALSE}
scenebreak = function() {
knitr::asis_output(if (knitr:::is_latex_output()) {
"\\scenebreak"
} else {
"<div style='text-align:center;'>•</div>"
})
}
```
Then use the function scenebreak() where a break is needed:
```{r echo=FALSE}
scenebreak()
```

Resources