使用 "details" HTML 标签切换块输出

Toggle chunk output using "details" HTML tag

我正在使用 blogdown 编写一些教程。出于教学原因,我希望我的学生在看到解决方案之前先思考一下。这是我当前的代码。

原创

---
title: "Toggle Chuck Output Using details Tag"
output: html_document
---

```{r calc, prompt=TRUE, eval=FALSE}
90 + 30
```

<details>
  <summary>Toggle output</summary>
```{r, ref.label='calc', echo=FALSE, prompt=TRUE}
```
</details>

这是我的尝试:

为了避免重复写HTML标签,我想我需要定义一个类似于...

的函数
togglable <- function(label, summary = "Toggle output"){
  cat('<details>')
  cat(' <summary>', summary, '</summary>', sep = '')

  # Code to print output using 'ref.label' should go here.
  # The following doesn't work. 
  knitr::knit_print(knitr:::knit_code$get(label))

  cat('</details>')
}

... 然后用类似于以下的 R 代码块替换 <detals>...</details> 块:

用例 1(更好)

```{r usecase1, echo=FALSE, results='asis'}
togglable(label = "calc")
```

我试图让它工作,但徒劳无功。

还有一件事。如果可能的话,我希望这个 togglable() 函数可以覆盖块选项,这样我什至不需要写 echo=FALSEresults='asis',因为下面的块看起来会更好。

用例 2(最佳)

```{r usecase2}
togglable(label = "calc")
```

综上所述,我想提出以下问题。

  1. 如何定义此 togglable() 函数,使其与原始 <detals>...</details> 块的行为相同?
  2. 此函数是否可能覆盖调用此函数的块的选项(特别是 echoresults)?如果是,如何?
  3. 或者,有没有其他想法如何在不重复编写 HTML 标签的情况下产生原始代码的结果?

非常感谢!

这可以通过 chunk option ref.label (to reuse chunks), a chunk hook (to print the <details> tag) and a option hook 的组合来完成(在显示结果时更改块选项。

---
title: "Toggle Chuck Output Using details Tag"
output: html_document
---

```{r setup, include=FALSE}
library(knitr)

knit_hooks$set(showDetails = function(before, options, envir) {
  if (before) {
    return("<details>\n")
  } else {
    return("\n</details>")
  }
})

opts_hooks$set(showDetails = function(options) {
  if(options$showDetails) {
    options$echo = FALSE
    options$results = "asis"
  }
  return(options)
})
```
  
```{r calc, prompt=TRUE, eval=FALSE}
90 + 30
```


```{r, ref.label="calc", showDetails = TRUE}
```

工作原理:

  • 块挂钩在选项showDetails不是NULL的每个块前后执行。它打印 (returns) 相应的 HTML.
  • 选项挂钩调整每个块的其他选项(echoresultsshowDetailsTRUE

可以通过全局设置 calc 块的选项来进一步改进代码,这样您就不必为所有其他“仅显示代码”块重复它们:添加 opts_chunk$set(prompt = TRUE, eval = FALSE)到设置块和 options$eval = TRUE 到选项挂钩。

此外,如果您希望在使用 ref.label 时默认使用 <detail> 标签,您可以使用 ref.label 作为选项挂钩:

```{r setup, include=FALSE}
library(knitr)

opts_chunk$set(prompt = TRUE, eval = FALSE)

knit_hooks$set(showDetails = function(before, options, envir) {
  if (before) {
    return("<details>\n")
  } else {
    return("\n</details>")
  }
})

opts_hooks$set(ref.label = function(options) {
  options$echo = FALSE
  options$results = "asis"
  options$eval = TRUE
  options$showDetails = TRUE
  
  return(options)
})
```
  
```{r calc}
90 + 30
```


```{r, ref.label="calc"}
```