r r-markdown

Cómo agregar plegado de código a fragmentos de salida en documentos html rmarkdown



r-markdown (3)

Copié directamente el Javascript de la fuente de otro documento de Rmarkdown donde configuré code_folding: show . py_code_folding.js el javascript como py_code_folding.js y agregué <script src="py_code_folding.js"></script> en la parte superior de mi documento de Rmarkdown. La única limitación es que tuve que codificar en mi javascript si quiero que los bloques se muestren u oculten inicialmente.

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"); });

Realmente aprecio la función "code_folding" en RMarkdown. Sin embargo, lo que realmente necesito es que el código se muestre todo el tiempo y alternar la pantalla en la salida.

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

¿Hay alguna manera de alternar la salida en lugar del código? La mejor (pero no ideal) solución en la que he pensado es agregar collapse=TRUE a los fragmentos, pero luego el código y la salida aún se muestran al mismo tiempo.

Enlace al documento compilado: http://rpubs.com/daynefiler/188408


Una forma rápida y hacky de alternar una sección (no necesariamente el código):

Adjunte las secciones para alternar con <div class="toggle"><button>TOGGLE_TEXT</button> y </div> en su archivo .Rmd

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>

Ponga esto en la parte inferior del archivo .Rmd (o idealmente en un archivo .js vinculado a todas sus páginas).

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

Pon esto en tu archivo .css (tendrás que jugar con la altura de tu botón).

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


TOC:

  1. Control total sobre qué trozos deben plegarse

  2. Dobla todos los fragmentos que contienen más de una línea de código / salida

1. Control total sobre qué trozos deben plegarse

También quería tener la misma funcionalidad e hice lo siguiente:

Creé un JavaScript que se ve de la siguiente manera:

$(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''); }); });

Como no soy un crack de JS, puede que no sea perfecto, pero hace lo que se supone que debe hacer. Inclúyalo en su archivo Rmd:

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

También escribí algunas definiciones CSS para diseñar el botón:

.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; }

Después de incluir ambos, el archivo JS y la hoja de estilo, puede ocultar fragmentos envolviendo un contenedor div a su alrededor con una de las siguientes clases:

Ocultar solo salida

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

Ocultar código fuente

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

Ocultar ambos

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

El script detecta el tipo de cada fragmento (por ejemplo, código fuente, salida de texto o salida de trazado) y etiqueta los botones en consecuencia.

El resultado se ve así:

2. Doble todos los fragmentos que contengan más de una línea de código / salida

Aquí hay una versión del script que agrega la función de plegado a todos los fragmentos que son más largos que una línea:

$(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''); }); });

Simplemente <script src="js/hideAll.js"></script> con <script src="js/hideAll.js"></script> y no necesita envolver contenedores div alrededor de sus fragmentos de código. Sin embargo, una cosa que debe agregar en su documento Rmd es la siguiente opción de fragmento global:

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

Es necesario para identificar la salida gráfica.