xaringan icon indicating copy to clipboard operation
xaringan copied to clipboard

xaringan breaks on unmatched "]" within code chunk

Open k-hench opened this issue 3 years ago • 7 comments

I stumbled upon a weird issue that is breaking my xaringan presentation: Apparently the including an unmatched "]" within a string in a code chunk is being interpreted as closing a css-class specifier and thus closes the code chunk prematurely.

Here is a minimal example of the problem - in my case the code chunk in the right column of slide 2 does not render correctly and interferes with the column definition itself.

I render the following file (xaringan_bugtrace.Rmd), using either the "knit"-button within RStudio, or by running rmarkdown::render("xaringan_bugtrace.Rmd") :

---
title: "Xaringan wtf ']'?"
output:
  xaringan::moon_reader:
    lib_dir: libs
---

```{r setup, include=FALSE}
options(htmltools.dir.version = FALSE)
```

.pull-left[
works nicely
```{r}
cat("test")
```
]

.pull-right[
breaks
```{r}
cat('test]')
```
]

which results in the following broken slide:

A similar thing happens when the unmatched ] appears in a results code block (eg. when replacing the cat("test]") with cut(1:5,breaks = c(0,2,5))):

Stackoverflow ref:

https://stackoverflow.com/questions/67651622/how-to-include-an-unmatched-within-a-rmarkdown-xaringan-code-chunk

Session info:

R version 4.0.2 (2020-06-22)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.2 LTS, RStudio 1.4.1717

Locale:
  LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=de_DE.UTF-8        LC_COLLATE=en_US.UTF-8    
  LC_MONETARY=de_DE.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=de_DE.UTF-8       LC_NAME=C                 
  LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=de_DE.UTF-8 LC_IDENTIFICATION=C       

Package version:
  base64enc_0.1.3   BH_1.75.0.0       digest_0.6.27     evaluate_0.14     glue_1.4.2        graphics_4.0.3    grDevices_4.0.3  
  highr_0.8         htmltools_0.5.1.1 httpuv_1.5.5      jsonlite_1.7.2    knitr_1.31        later_1.1.0.1     magrittr_2.0.1   
  markdown_1.1      methods_4.0.3     mime_0.10         promises_1.2.0.1  R6_2.5.0          Rcpp_1.0.6        rlang_0.4.11     
  rmarkdown_2.7.6   servr_0.21        stats_4.0.3       stringi_1.5.3     stringr_1.4.0     tinytex_0.31.3    tools_4.0.3      
  utils_4.0.3       xaringan_0.21.1   xfun_0.22         yaml_2.2.1.99   

By filing an issue to this repo, I promise that

  • [x] I have fully read the issue guide at https://yihui.org/issue/.
  • [x] I have provided the necessary information about my issue.
    • If I'm asking a question, I have already asked it on Stack Overflow or RStudio Community, waited for at least 24 hours, and included a link to my question there.
    • If I'm filing a bug report, I have included a minimal, self-contained, and reproducible example, and have also included xfun::session_info('xaringan'). I have upgraded all my packages to their latest versions (e.g., R, RStudio, and R packages), and also tried the development version: remotes::install_github('yihui/xaringan').
    • If I have posted the same issue elsewhere, I have also mentioned it in this issue.
  • [x] I have learned the Github Markdown syntax, and formatted my issue correctly.

I understand that my issue may be closed if I don't fulfill my promises.

k-hench avatar Jun 09 '21 12:06 k-hench

I think this is a remark.js behavior - See https://github.com/gnab/remark/issues/189 and Wiki documentation https://github.com/gnab/remark/wiki/Markdown#content-classes

In case of nested brackets, you can use HTML codes:

.footnote[.red.bold[*] Opening bracket: []

It seems a bit trickier here as this happens in code part and the HTML code does not seem to work. Unless results = "asis" is set to the chunk output so that it is not included into a markdown code block. (This happens because I don't think remark.js will evaluate raw HTML inside a markdown block.)

---
title: "Xaringan wtf ']'?"
output:
  xaringan::moon_reader:
    lib_dir: libs
---

```{r setup, include=FALSE}
options(htmltools.dir.version = FALSE)
```

.pull-left[
works nicely
```{r}
cat("test")
```
]

.pull-right[
breaks
```{r, results="asis"}
cat('test]')
```
]

@yihui did you encounter this ? Do we have tools to handle the HTML escaping of such thing ?

This seems like a limitation of remarkjs not so simple to overcome. (but could be with hooks or else maybe?)

cderv avatar Jun 09 '21 14:06 cderv

@cderv I haven't encountered this myself, although I was aware of this issue. I also feel it won't be simple to overcome. I guess we can escape unbalanced ] as ] with source and output hooks, and restore it after remark.js has rendered the slides. The tricky thing is how to precisely restore the ] that we previously escaped, i.e., what if users have a verbatim string ] in the slides? We need to mark the string ] as special when it is from an escaped ]. I don't know what a reasonable implementation would be.

yihui avatar Jun 09 '21 20:06 yihui

Yes I was thinking the same. It won't be simple. It will require some thinking.

@k-hench can I asked the use case ? The real life example you have ? Is it in a cat output inside a code chunk as in the small example ? Thanks.

cderv avatar Jun 09 '21 21:06 cderv

So, the real life example was connected to a ggplot-tutorial, in which I wanted to pre-set values for a binned color scale. For this I was creating a named color vector, for which the names need to match the ranges of the binned variable. I believe the binning happens with cut() or similar, in any case the names of the color vector need to specify a range in the form of (x1, x2].

A small code example of what I was trying to show (and my current hacky solution, which is to include #[ in the code before):

---
title: "Xaringan wtf ']'?"
output:
  xaringan::moon_reader:
    lib_dir: libs
    nature:
      ratio: '16:9'
---

```{r setup, include=FALSE}
options(htmltools.dir.version = FALSE)
```

.pull-left[
```{r, eval=FALSE}
library(tidyverse)
library(raster)
library(ggspatial)
library(RColorBrewer)

brks <- c(-Inf, -30, -10, -5,
          0, 5, 10, 50, Inf)
# [ <- current hacky solution
clr_atlas<-c(rev(
  brewer.pal(5, "Greys")[1:4]), 
  brewer.pal(5, "Greens")[2:5]) %>%
  set_names(nm = str_c("(",
                       brks[1:8], ", ",
                       brks[2:9], "]"))

ggplot(df_spatial(raster(volcano))) +
  geom_contour_filled(
    aes(x = x , y = y,
        z = band1- 120,
        fill = stat(level)),
    breaks = brks) +
  scale_fill_manual("Height",
                    values = clr_atlas)
```
]


.pull-right[
```{r, message=FALSE, warning=FALSE, echo = FALSE, dev.args= list(type = "cairo")}
library(tidyverse)
library(raster)
library(ggspatial)
library(RColorBrewer)

brks <- c(-Inf, -30, -10, -5,
          0, 5, 10, 50, Inf)
# [ <- current hacky solution
clr_atlas<-c(rev(
  brewer.pal(5, "Greys")[1:4]), 
  brewer.pal(5, "Greens")[2:5]) %>%
  set_names(nm = str_c("(",
                       brks[1:8], ", ",
                       brks[2:9], "]"))

ggplot(df_spatial(raster(volcano))) +
  geom_contour_filled(
    aes(x = x , y = y,
        z = band1- 120,
        fill = stat(level)),
    breaks = brks) +
  scale_fill_manual("Height",
                    values = clr_atlas)
```
]

This results in this slide:

k-hench avatar Jun 10 '21 16:06 k-hench

Has there been any progress on this issue? I am experiencing it on panel slides. It always adds a random ] after the heading and before the panels. I found the line by inspecting the output source element, but I can't find a way to make it go away. I can delete it from my immediate view, but I can't save the change. It reappears when I open the document.

Screen Shot 2023-01-09 at 9 05 32 AM Screen Shot 2023-01-20 at 10 07 45 PM

DancinByMoonlight avatar Jan 21 '23 21:01 DancinByMoonlight

@DancinByMoonlight Can you share the original Rmd or link to the source (or a smaller example that reproduces the problem)?

gadenbuie avatar Jan 21 '23 23:01 gadenbuie

I'm a new member to github because I was hoping for help with this problem. I tried to upload an rmd file, but it says that type isn't accepted. It doesn't allow the html file, either. But I did copy/paste some example code in here. I hope it's in an okay format.

```
---
Class: Center

##Panel Slide 1
```{r panelset = TRUE, layout='l-page', echo=FALSE}
xaringanExtra::use_panelset()

```
<style>.panelset{
  --panel-tab-foreground:#E2D700;
  --panel-tab-background: #627174;
  --panel-tab-active-foreground: #F26838;
  --panel-tab-active-background: #212121;
  --panel-tab-active-border-color: currentColor;
  --panel-tab-hover-foreground: currentColor;
  --panel-tab-hover-background: #747474;
  --panel-tab-hover-border-color: currentColor;
  --panel-tab-inactive-opacity: 0.6;
  --panel-tab-border-bottom:#ddd
}</style>

<div class = 'panelset'>
.panelset[.panel[.panel-name[Slide 1, Tab 1]
.pull-left[
* Content

* More content

* Some more things
]]

.pull-right[
<img src = "https://images.pexels.com/photos/2693208/pexels-photo-2693208.png?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
align = "top"/>
]
]

.panel[.panel-name[Slide 1, Tab 2]
```{r message = FALSE, echo = FALSE, warning = FALSE, fig.align = 'center'}

####code for ggplotly graph.  it works great.---

```
]


DancinByMoonlight avatar Jan 22 '23 01:01 DancinByMoonlight