codehover
Pipes are an excellent way to code. They make it easy to follow the code chain of transformations and their results.
The codehover aims to make it easy to create a HTML table with a simple hover effect (plain CSS and JavaScript, bundled with the package) that shows images beside or below the said table. Rows also react to tap and to the keyboard, so the result works on a phone and for keyboard users too.
This way one could set up pseudo-lines of code (show as text) in the table and a series of images showing the intermediate results of the code with a hovering interaction.
The package use is educational, a fast way of showing code actions.
I have to say that I begin with the ideia of the package without knowing about a simillar package based on Xaringan: flipbookr. In fact, I guess it was in my subconscious all along, for I follow Gina Reynolds work on Twitter for a long time. She made a wonderful job there, way more sophisticated than I even hope to implement here. codehover is aimed at a HTML page (through RMarkdown), with hover effect . By virtue of those simple differences I will keep the package online (until she implements the same functionality on flipbookr - granted that she already shows how to embed xaringan presentation into HTML(here)).
Installation
You can install the experimental version of codehover from github:
install.packages("devtools")
devtools::install_github("arthurwelle/codehover")Since version 1.0.0 no set-up is needed: the object returned by
ch_out() (and by ch_hover()) carries its own
CSS and JavaScript as an htmltools dependency, so it
renders in any R Markdown or Quarto document – and in the RStudio viewer
– and the knitted HTML is self-contained.
Two RMarkdown Templates are installed with the package as a starting point (File -> New File -> R Markdown -> From Template): codehover for the automatic mode and codehover-manual for the hand-built tables shown below. They are convenience only – a plain .Rmd works just as well. As with any new template, it may take an RStudio restart to show up in the menu.
Workflow example
Load some libraries:
Let´s try to replicate the following graph (code and intermediate steps).
ggplot() +
geom_point(data = cars,
aes(x = speed,
y = dist,
color = 'red')) +
scale_y_continuous(limits = c(0,100)) +
labs(title = 'A ggplot fot the rest of us',
subtitle = 'Testing a way of explicit showing the R workflow') +
theme_bw()
Save every step as an image.
# create IMG folted
dir.create("./IMG/")
#> Warning in dir.create("./IMG/"): '.\IMG' already exists
g <- ggplot2::ggplot() +
geom_point(data = cars,
aes(x = speed,
y = dist))
ggplot2::ggsave("./IMG/1b.png", width = 4, height = 3)
g <- g + aes(color = "red")
ggplot2::ggsave("./IMG/2b.png", width = 4, height = 3)
g <- g + scale_y_continuous(limits = c(0,100))
ggplot2::ggsave("./IMG/3b.png", width = 4, height = 3)
#> Warning: Removed 1 row containing missing values or values outside the scale range
#> (`geom_point()`).
g <- g + labs(title = "A ggplot fot the rest of us")
ggplot2::ggsave("./IMG/4b.png", width = 4, height = 3)
#> Warning: Removed 1 row containing missing values or values outside the scale range
#> (`geom_point()`).
g <- g + labs(subtitle = "Testing a way of explicit showing the R workflow")
ggplot2::ggsave("./IMG/5b.png", width = 4, height = 3)
#> Warning: Removed 1 row containing missing values or values outside the scale range
#> (`geom_point()`).
g <- g + theme_bw()
ggplot2::ggsave("./IMG/6b.png", width = 4, height = 3)
#> Warning: Removed 1 row containing missing values or values outside the scale range
#> (`geom_point()`).codehover has three functions that should be used together in a
pipe-like style: ch_int(), ch_row(), and
ch_out().
ch_int() initiates the HTML table, one can choose if the
hover effect will be incremental or for a single row of the table. You
can pass a custom CSS class for the whole table here as well.
After that you can use multiple ch_row calls to make as
many rows as you like in the HTML table. For every line you should pass
a text (the pseudo code you want to show) and an image. By
default codehover uses knitr to
encode the image file as a base64 string, with that your final HTML is
self-contain in just one file (the images would be inside it). With
multiple images this can increase file size considerable, so it´s
optional to pass an url (with url = TRUE) if you dont want the behavior
of embeding images. This way you can host your images anywhere.
Note that the code (the pseudo-code as text) use some <tabs> and for indentation of the final text displayed. See more of that bellow.
Finally you show close the table with the function
ch_out. Here you can indicate another image to be show
before any hover interaction, as well as to pass another CSS class to
the image holder to control its size and placement in the page.
With these three functions you create an object that is already
renderable – its CSS and JavaScript come attached – so you just print
it. (Up to version 0.0.1 the result was a plain string that had to be
passed through htmltools::HTML(); that step is gone.)
ch_out() also takes alt = for the image’s
alternative text, caption = and aspect =.
result <- ch_int(type = "incremental") %>%
ch_row(text =
"ggplot() +
<br> <tab1> geom_point(data = cars, </tab1>
<br> <tab2> aes(x = speed, </tab2>
<br> <tab2> y = dist, </tab2>",
img ="./IMG/1b.png") %>%
ch_row(text = "<tab2> color = 'red')) + </tab2>",
img ="./IMG/2b.png") %>%
ch_row(text = "<tab1> scale_y_continuous(limits = c(0,100)) + </tab1>",
img ="./IMG/3b.png") %>%
ch_row(text = "<tab1> labs(title = 'A ggplot fot the rest of us', </tab1>",
img ="./IMG/4b.png") %>%
ch_row(text = "<tab2> subtitle = 'Testing a way of explicit showing the R workflow') + </tab2>",
img ="./IMG/5b.png") %>%
ch_row(text = "<tab1> theme_bw()</tab1> ",
img ="./IMG/6b.png") %>%
ch_out(img = "./IMG/1b.png")
Since version 1.0.0 the object returned by ch_out() is
already renderable (its CSS and JavaScript are attached automatically) –
just print it.
result| ggplot() +
|
Writing style (bits and quirks)
Quotes
From Quotes we see than “single quotes are normally only used to delimit character constants containing double quotes”. This is the exactlly use here, we have to use single quotes in the R code that we want to pass as text for the HTML table.
For exemple, if we want to pass a ggplot2 title we could interchangebly use labs(title = “A Title”) or labs(title = ‘A Title’), but if we want to pass this as text to codehover we should use single quotes.
ch_row(text = “labs(title = ‘A Title’)”)
Indentation
You can use the <br> tag to initiate new lines.
And to proper indent your text, as you would like to do to a code, you can use the HTML non-breaking spaces.
a single non-breaking space;
  = it is equal to two
  = it is equal to four
Alternatively the codehover CSS has the classes ch-tab1
to ch-tab16 to denote 1 to 16 indentation levels (each
level is --codehover-tab, 2em by default). To use them you
enclose the text in a span. For example:
ch_row(text = “<span class=‘ch-tab7’>theme_bw()</span>”)
The bare <tab1> … <tab16> tags used up to version 0.0.1 are still styled, so older documents keep working.
Under the hood
There is no jQuery and no script to copy any more. Each row is
written as <tr data-link="...">, and the vanilla
JavaScript shipped inside the package
(inst/assets/codehover.js, attached automatically) listens
for hover, tap, focus and arrow keys, then swaps the src of
the image holder. Everything is scoped under the .codehover
class, so it cannot collide with the rest of your page.
You can restyle it with the CSS custom properties exposed by the package:
.codehover {
--codehover-highlight: #F1D95A; /* row highlight */
--codehover-font: monospace; /* code font */
--codehover-font-size: 0.9em;
--codehover-tab: 2em; /* width of one indent level */
}Reference
The codehover hex sticker was made using the R package hexSticker.