如何在rmarkdown html文档中添加代码折叠到输出块

时间:2016-06-10 18:31:10

标签: r r-markdown

我非常感谢RMarkdown中的“code_folding”功能。但是,我真正需要的是让代码始终显示并在输出上切换显示。

tar -zcvf archive-name.tar.gz -C directory-name .

有没有办法切换输出而不是代码?我想到的最好(但不是理想的)解决方案是将--- title: "test file" author: "dayne" date: "June 10, 2016" output: html_document: code_folding: hide --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` Here is a basic example. ```{r} 3 + 4 ``` 添加到块中,但代码和输出仍然同时显示。

链接到已编译的文档:http://rpubs.com/daynefiler/188408

4 个答案:

答案 0 :(得分:30)

<强> TOC:

  1. 完全控制应折叠的块

  2. 折叠包含多行代码/输出的所有块

  3. 1。完全控制应折叠的块

    我也想拥有相同的功能并执行以下操作:

    我创建了一个看起来如下的JavaScript:

    $(document).ready(function() {
    
      $chunks = $('.fold');
    
      $chunks.each(function () {
    
        // add button to source code chunks
        if ( $(this).hasClass('s') ) {
          $('pre.r', this).prepend("<div class=\"showopt\">Show Source</div><br style=\"line-height:22px;\"/>");
          $('pre.r', this).children('code').attr('class', 'folded');
        }
    
        // add button to output chunks
        if ( $(this).hasClass('o') ) {
          $('pre:not(.r)', this).has('code').prepend("<div class=\"showopt\">Show Output</div><br style=\"line-height:22px;\"/>");
          $('pre:not(.r)', this).children('code:not(r)').addClass('folded');
    
          // add button to plots
          $(this).find('img').wrap('<pre class=\"plot\"></pre>');
          $('pre.plot', this).prepend("<div class=\"showopt\">Show Plot</div><br style=\"line-height:22px;\"/>");
          $('pre.plot', this).children('img').addClass('folded');
    
        }
      });
    
      // hide all chunks when document is loaded
      $('.folded').css('display', 'none')
    
      // function to toggle the visibility
      $('.showopt').click(function() {
        var label = $(this).html();
        if (label.indexOf("Show") >= 0) {
          $(this).html(label.replace("Show", "Hide"));
        } else {
          $(this).html(label.replace("Hide", "Show"));
        }
        $(this).siblings('code, img').slideToggle('fast', 'swing');
      });
    });
    

    因为我不是JS破解它可能不是完美的,但它做了它应该做的事情。 将其包含在您的Rmd文件中:

    <script src="js/hideOutput.js"></script>
    

    我还写了一些CSS定义来设置按钮的样式:

    .showopt {
      background-color: #004c93;
      color: #FFFFFF; 
      width: 100px;
      height: 20px;
      text-align: center;
      vertical-align: middle !important;
      float: right;
      font-family: sans-serif;
      border-radius: 8px;
    }
    
    .showopt:hover {
        background-color: #dfe4f2;
        color: #004c93;
    }
    
    pre.plot {
      background-color: white !important;
    }
    

    在包含JS文件和样式表之后,您可以通过使用以下类之一包装div容器来隐藏块:

    仅隐藏输出

    <div class="fold o">
    ```{r}
      ...
    ```
    </div>
    

    隐藏源代码

    <div class="fold s">
    ```{r}
      ...
    ```
    </div>
    

    同时隐藏

    <div class="fold s o">
    ```{r}
      ...
    ```
    </div>
    

    脚本检测每个块的类型(例如源代码,文本输出或绘图输出)并相应地标记按钮。

    结果如下:

    enter image description here

    enter image description here

    2。折叠包含多行代码/输出

    的所有块

    以下是脚本的一个版本,它将折叠功能添加到长于一行的所有块中:

    $(document).ready(function() {
      $plots = $('img.plot');
      $chunks = $('pre').has('code');
      $chunks = $chunks.filter(function(idx) {
        return $(this).children('code').outerHeight(false) > parseInt($(this).css('line-height'));
      });
    
      $chunks.each(function () {
        if($(this).hasClass('r')) {
          $(this).append("<div class=\"showopt\">Show Source</div><br style=\"line-height:22px;\"/>");
        } else {
          $(this).append("<div class=\"showopt\">Show Output</div><br style=\"line-height:22px;\"/>");
        }
      });
    
      $plots.each(function () {
        $(this).wrap('<pre class=\"plot\"></pre>');
        $(this).parent('pre.plot').prepend("<div class=\"showopt\">Show Plot</div><br style=\"line-height:22px;\"/>");
      });
    
      // hide all chunks when document is loaded
      $chunks.children('code').toggle();
      $('pre.plot').children('img').toggle();
      // function to toggle the visibility
      $('.showopt').click(function() {
        var label = $(this).html();
        if (label.indexOf("Show") >= 0) {
          $(this).html(label.replace("Show", "Hide"));
        } else {
          $(this).html(label.replace("Hide", "Show"));
        }
        $(this).siblings('code, img').slideToggle('fast', 'swing');
      });
    });
    

    只需将其包含在<script src="js/hideAll.js"></script>中,您就不需要在代码块周围包装div容器。 您必须在Rmd文档中添加的一件事是以下全局块选项:

    ```{r, echo = F}
    knitr::opts_chunk$set(out.extra = 'class="plot"')
    ```
    

    需要识别图形输出。

答案 1 :(得分:11)

这种低保真解决方案怎么样?

<details><summary>Click here</summary>
Some text

```{r code}
# even code
print("Hello world!")
```
</details>

不是我的,但我喜欢。

答案 2 :(得分:2)

切换一个部分(不一定是代码)的快速黑客方式:

将这些部分与您的.Rmd文件中的<div class="toggle"><button>TOGGLE_TEXT</button><\div>进行切换

1. How many users are in the second, but not the first, user table?

    <div class="toggle"><button>Solution</button>
    ```{r}
    setdiff(user2, user) %>% nrow()
    ```
    </div>

将它放在.Rmd文件的底部(或理想情况下,链接到所有页面的.js文件中)。

<script>
  $(".toggle").click(function() {
    $(this).toggleClass("open");
  });
</script>

将它放在.css文件中(您必须使用按钮的高度)。

.toggle {
  height: 1.55em;
  overflow-y: hidden;
}
.toggle.open {
  height: auto;
}

答案 3 :(得分:0)

我直接从我设置code_folding: show的另一个Rmarkdown文档的源代码中复制了javascript。我将javascript保存为py_code_folding.js,并将<script src="py_code_folding.js"></script>添加到我的Rmarkdown文档的顶部。唯一的限制是我必须在我的javascript中硬编码我是否希望最初显示或隐藏块。

window.initializePythonCodeFolding = 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 = 10000;

  // select all R code blocks
  var rCodeBlocks = $('pre.python');
  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');
    });
  });

}

$(document).ready(function () {
  window.initializePythonCodeFolding("show" === "show");
});