预订中的代码折叠

时间:2017-07-27 21:05:25

标签: javascript html r code-folding bookdown

RMarkdown中用于html文档的代码折叠选项非常棒。该选项使得程序化方法对于那些感兴趣的人来说是透明的,而不会迫使观众滚动数英里的代码。通过散文和交互式图形输出紧密放置代码,使整个项目更容易被更广泛的用户访问,而且还减少了对额外文档的需求。

对于一个更大的项目,我正在使用bookdown,它运作良好。唯一的问题是没有代码折叠选项。 在记事本中当前未启用代码折叠。 (见Enable code folding in bookdown

我知道我不需要一个选项来实现它。我只需要将正确的代码粘贴到正确的位置或地方。但是什么代码和在哪里?

一个可行的替代方案是将代码块放在页面中块的输出下面。或者,最后,将它们作为附录。我可以用html做到这一点,但不像rbookdown那样可重复。

3 个答案:

答案 0 :(得分:20)

整个页面的全局隐藏/显示按钮

要使用@Yihui的提示获取折叠html输出中所有代码的按钮,您需要将以下代码粘贴到外部文件中(我将其命名为header.html):

修改:我修改了功能toggle_R,以便点按该按钮时显示Hide GlobalShow Global

<script type="text/javascript">

// toggle visibility of R source blocks in R Markdown output
function toggle_R() {
  var x = document.getElementsByClassName('r');
  if (x.length == 0) return;
  function toggle_vis(o) {
    var d = o.style.display;
    o.style.display = (d == 'block' || d == '') ? 'none':'block';
  }

  for (i = 0; i < x.length; i++) {
    var y = x[i];
    if (y.tagName.toLowerCase() === 'pre') toggle_vis(y);
  }

    var elem = document.getElementById("myButton1");
    if (elem.value === "Hide Global") elem.value = "Show Global";
    else elem.value = "Hide Global";
}

document.write('<input onclick="toggle_R();" type="button" value="Hide Global" id="myButton1" style="position: absolute; top: 10%; right: 2%; z-index: 200"></input>')

</script>

在此脚本中,您可以使用style选项直接修改与按钮关联的位置和CSS代码,或将其添加到css文件中。我必须将z-index设置为较高的值,以确保它出现在其他分区上 请注意,此javascript代码仅折叠使用echo=TRUE调用的R代码,该代码在html中归为class="r"。这由命令var x = document.getElementsByClassName('r');

定义

然后,您在rmarkdown脚本的YAML标题中调用此文件,如下例所示:

---
title: "Toggle R code"
author: "StatnMap"
date: '`r format(Sys.time(), "%d %B, %Y")`'
output:
  bookdown::html_document2:
    includes:
      in_header: header.html
  bookdown::gitbook:
    includes:
      in_header: header.html
---

Stackoverflow question
<https://stackoverflow.com/questions/45360998/code-folding-in-bookdown>

```{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)
```

新编辑:每个块的本地隐藏/显示按钮

我终于找到了解决方案!
在查看正常html输出的代码折叠行为(没有减记)时,我能够将其添加到bookdown。主要的javascript函数需要找到.sourceCode类分区来处理bookdown。但是,这也需要bootstrap的补充javascript函数,但不是全部。这适用于gitbookhtml_document2 以下是步骤:

  1. 在与Rmd文件相同的目录中创建js文件夹
  2. 在此处下载javascript函数transition.jscollapse.js,例如:https://github.com/twbs/bootstrap/tree/v3.3.7/js并将其存储在js文件夹
  3. 使用以下代码在名为js的{​​{1}}文件夹中创建一个新文件。这与rmarkdown code_folding选项相同,但添加了codefolding.js以查找R代码块:
  4. pre.sourceCode代码:

    codefolding.js
    1. 在下面的rmarkdown脚本中,所有三个函数都被读取并包含在标题中,因此window.initializeCodeFolding = function(show) { // handlers for show-all and hide all $("#rmd-show-all-code").click(function() { $('div.r-code-collapse').each(function() { $(this).collapse('show'); }); }); $("#rmd-hide-all-code").click(function() { $('div.r-code-collapse').each(function() { $(this).collapse('hide'); }); }); // index for unique code element ids var currentIndex = 1; // select all R code blocks var rCodeBlocks = $('pre.sourceCode, pre.r, pre.python, pre.bash, pre.sql, pre.cpp, pre.stan'); rCodeBlocks.each(function() { // create a collapsable div to wrap the code in var div = $('<div class="collapse r-code-collapse"></div>'); if (show) div.addClass('in'); var id = 'rcode-643E0F36' + currentIndex++; div.attr('id', id); $(this).before(div); $(this).detach().appendTo(div); // add a show code button right above var showCodeText = $('<span>' + (show ? 'Hide' : 'Code') + '</span>'); var showCodeButton = $('<button type="button" class="btn btn-default btn-xs code-folding-btn pull-right"></button>'); showCodeButton.append(showCodeText); showCodeButton .attr('data-toggle', 'collapse') .attr('data-target', '#' + id) .attr('aria-expanded', show) .attr('aria-controls', id); var buttonRow = $('<div class="row"></div>'); var buttonCol = $('<div class="col-md-12"></div>'); buttonCol.append(showCodeButton); buttonRow.append(buttonCol); div.before(buttonRow); // update state of button on show/hide div.on('hidden.bs.collapse', function () { showCodeText.text('Code'); }); div.on('show.bs.collapse', function () { showCodeText.text('Hide'); }); }); } 文件夹对最终文档本身无用。在阅读js函数时,我还默认为js代码块添加了选项,但您可以选择使用show隐藏它们。
    2. rmarkdown代码:

      hide

      此脚本显示Rstudio浏览器中的按钮,但效果不佳。但是,这对firefox来说没问题 您会看到此代码中有一点--- title: "Toggle R code" author: "StatnMap" date: '`r format(Sys.time(), "%d %B, %Y")`' output: bookdown::html_document2: includes: in_header: header.html bookdown::gitbook: includes: in_header: header.html --- Stackoverflow question <https://stackoverflow.com/questions/45360998/code-folding-in-bookdown> ```{r setup, include=FALSE} # Add a common class name for every chunks knitr::opts_chunk$set( echo = TRUE) ``` ```{r htmlTemp3, echo=FALSE, eval=TRUE} codejs <- readr::read_lines("js/codefolding.js") collapsejs <- readr::read_lines("js/collapse.js") transitionjs <- readr::read_lines("js/transition.js") htmlhead <- paste(' <script>', paste(transitionjs, collapse = "\n"), '</script> <script>', paste(collapsejs, collapse = "\n"), '</script> <script>', paste(codejs, collapse = "\n"), '</script> <style type="text/css"> .code-folding-btn { margin-bottom: 4px; } .row { display: flex; } .collapse { display: none; } .in { display:block } </style> <script> $(document).ready(function () { window.initializeCodeFolding("show" === "show"); }); </script> ', sep = "\n") readr::write_lines(htmlhead, path = "header.html") ``` ## 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) ``` ```{r plot} plot(cars) ``` ,但当然您可以使用更多css修改位置和颜色以及您想要的任何内容。

      编辑:组合全局和本地按钮

      编辑2017-11-13:全局代码折叠按钮与各个bloc按钮很好地集成。函数css最终不是必需的,但您需要获取函数{{1}在bootstrap中。

      调用toggle_R文件时,在代码块中直接调用全局按钮:

      dropdown.js

      新的全局按钮会显示一个下拉菜单,可以选择&#34;显示所有代码&#34;或者&#34;隐藏所有代码&#34;。使用js默认情况下会显示所有代码,而使用```{r htmlTemp3, echo=FALSE, eval=TRUE} codejs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/codefolding.js") collapsejs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/collapse.js") transitionjs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/transition.js") dropdownjs <- readr::read_lines("/mnt/Data/autoentrepreneur/js/dropdown.js") htmlhead <- c( paste(' <script>', paste(transitionjs, collapse = "\n"), '</script> <script>', paste(collapsejs, collapse = "\n"), '</script> <script>', paste(codejs, collapse = "\n"), '</script> <script>', paste(dropdownjs, collapse = "\n"), '</script> <style type="text/css"> .code-folding-btn { margin-bottom: 4px; } .row { display: flex; } .collapse { display: none; } .in { display:block } .pull-right > .dropdown-menu { right: 0; left: auto; } .open > .dropdown-menu { display: block; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; text-align: left; list-style: none; background-color: #fff; -webkit-background-clip: padding-box; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0,0,0,.15); border-radius: 4px; -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175); box-shadow: 0 6px 12px rgba(0,0,0,.175); } </style> <script> $(document).ready(function () { window.initializeCodeFolding("show" === "show"); }); </script> ', sep = "\n"), paste0(' <script> document.write(\'<div class="btn-group pull-right" style="position: absolute; top: 20%; right: 2%; z-index: 200"><button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" data-_extension-text-contrast=""><span>Code</span> <span class="caret"></span></button><ul class="dropdown-menu" style="min-width: 50px;"><li><a id="rmd-show-all-code" href="#">Show All Code</a></li><li><a id="rmd-hide-all-code" href="#">Hide All Code</a></li></ul></div>\') </script> ') ) readr::write_lines(htmlhead, path = "/mnt/Data/autoentrepreneur/header.html") ``` 时,默认情况下会隐藏所有代码。

答案 1 :(得分:2)

我为pandoc编写了一个过滤器:

  • 将所有代码块包装在HTML5 <details>标签中
  • 添加本地按钮以折叠/展开代码
  • 按钮文本通过onclick JavaScript事件在“显示代码”和“隐藏代码”之间切换(随意定制)

可以找到过滤器here。需要安装pythonpanflute发行版才能运行。

通过pandoc_args: ["-F", "path/to/collapse_code.py"]

添加到书本中

答案 2 :(得分:2)

我制作了R软件包rtemps,其中包括一个现成的书本模板,其中带有代码折叠按钮(主要基于塞巴斯蒂安·罗切特的回答/帖子)。选中here