12.3 Scrollable text output

In Section 7.4, we showed how to restrict the heights of code blocks and text output blocks via CSS. In fact, there is a simpler method with the chunk options attr.source and attr.output to add the style attribute to the fenced code blocks in the Markdown output (see Section 11.13 for more information on these options). For example, for this code chunk with the attr.output option:

```{r, attr.output='style="max-height: 100px;"'}
1:300
```

Its Markdown output will be:

```r
1:300
```

```{style="max-height: 100px;"}
##   [1]   1   2   3   4   5   6   7   8   9  10
##  [11]  11  12  13  14  15  16  17  18  19  20
##  ... ...
```

Then the text output block will be converted to HTML by Pandoc:

<pre style="max-height: 100px;">
<code>##   [1]   1   2   3   4   5   6   7   8   9  10
##  [11]  11  12  13  14  15  16  17  18  19  20
##  ... ...</code>
</pre>

To learn more about Pandoc’s fenced code blocks, please read its manual at https://pandoc.org/MANUAL.html#fenced-code-blocks.

The attr.source and attr.output options have made it possible for us to specify maximum heights for individual code chunks. However, the syntax is a little clunky, and requires a better understanding of CSS and Pandoc’s Markdown syntax. Below we show an example of a custom output hook that works with a custom chunk option max.height, so you will only need to set the chunk option like max.height = "100px" instead of attr.output = 'style="max-height: 100px;"'. In this example, we only manipulate the options argument, but not the x argument.

---
title: Scrollable code blocks
output: 
  html_document: 
    highlight: tango
---

We set up an `output` hook to add a `style` attribute to the
text output when the chunk option `max.height` is set.

```{r, include=FALSE}
options(width = 60)
local({
  hook_output <- knitr::knit_hooks$get('output')
  knitr::knit_hooks$set(output = function(x, options) {
    if (!is.null(options$max.height)) options$attr.output <- c(
      options$attr.output,
      sprintf('style="max-height: %s;"', options$max.height)
    )
    hook_output(x, options)
  })
})
```

Without the `max.height` option, you will see the full output,
e.g.,

```{r}
1:100
```

Now we set `max.height` to `100px`. You will see a scrollbar
in the text output because its height is larger than 100px.

```{r, max.height='100px'}
1:100
```

Essentially the `max.height` option is converted to the
`attr.output` option. It works even if the `attr.output`
option is present, i.e., it will not override the
`attr.output` option, e.g., we show line numbers on the left
side of the text output via the `.numberLines` attribute:

```{r, max.height='100px', attr.output='.numberLines'}
1:100
```

Figure 12.1 shows the output. Note that in the last code chunk with the chunk option attr.output, the option will not be overridden by max.height because we respect existing attributes by combining them with the style attribute generated by max.height:

options$attr.output <- c(
  options$attr.output,
  sprintf('style="max-height: %s;"', options$max.height)
)
An example of scrollable text output, with its height specified in the chunk option max.height.

FIGURE 12.1: An example of scrollable text output, with its height specified in the chunk option max.height.

You can use a similar trick in the source hook to limit the height of source code blocks.