{pegboard}: Parse Source Files in The Carpentries Workbench

options(width = 300)
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#|",
  fig.path = "man/figures/README-",
  out.width = "100%"
)

pegboard status badge R-CMD-check status Codecov test coverage Lifecycle: experimental CRAN status

[pegboard] is tempered hardboard which is pre-drilled with evenly spaced holes. The holes are used to accept pegs or hooks to support various items, such as tools in a workshop.

https://en.wikipedia.org/wiki/Pegboard

The {pegboard} package is part of The Carpentries Workbench and it's main functionality is to parse Markdown and R Markdown documents into XML representations (via {tinkr}). By using XML, we are able to easily arrange and parse the elements of the lessons which makes two things possible:

There are two {R6} objects in the package:

One simple usage is getting a summary of the content of an episode. Let's investigate the contents of the "Episode Structure" episode of the Workbench documentation:

library("pegboard")
library("withr")
# Download the file we need ------------------------------------
src <- "https://raw.githubusercontent.com/carpentries/sandpaper-docs/main/episodes/episodes.Rmd"
tmp <- local_tempfile(fileext = ".Rmd")
download.file(src, tmp)

# Load episode
ep <- Episode$new(tmp)
# Summary -------------------------------------------------------------
# confirm that we are using sandpaper and get a summary of the contents
ep$confirm_sandpaper()$summary()

# Validation ----------------------------------------------------------
# NOTE: a lot of invalid links because files do not exist outside of
#       the lesson context
lnk <- ep$validate_links()
str(lnk, max.level = 1)
hdg <- ep$validate_headings()
str(hdg, max.level = 1)
div <- ep$validate_divs()
str(div, max.level = 1)

Installation

{pegboard} is not currently on CRAN, but it can be installed from our Carpentries Universe (updated every hour) with the following commands:

options(repos = c(
  carpentries = "https://carpentries.r-universe.dev/", 
  CRAN = "https://cran.rstudio.com/"
))
install.packages("pegboard")

Example

To use {pegboard} in the context of The Workbench, you will need to have a lesson handy. If you don't have one, you can use the get_lesson() function, which will use {gert} to clone a lesson repository to your computer.

(NOTE: this file was last run on r Sys.time())

library("pegboard")
library("purrr")
library("xml2")
library("fs")

d <- fs::file_temp(pattern = "PBREADME")
rng <- get_lesson("swcarpentry/r-novice-gapminder", path = d, jekyll = FALSE)
rng

# Get a summary of all the elements in each episode
rng$summary()

# Validate lesson elements
rng$validate_links()
rng$validate_divs()
rng$validate_headings() # this is not run by default in sandpaper lessons

Manipulation

The XML contents of the lesson are contained within the $body element of the Episode object and anything you do to that XML document is retained within the object itself (see the {tinkr} documentation for more details):

ep1 <- rng$episodes[[1]]
ep1$body
ep1$head(20) # show the first 20 lines of the file
new_content <- r"{

#### NEW CONTENT

Hello! This is **new markdown content** generated via the 
[{pegboard}](https://carpentries.github.io/pegboard) package that will 
appear above the objectives block!

}"
ep1$add_md(new_content, where = 0L) 
ep1$head(20) # the new content has been added to the top
ep1$headings[[1]] # the first heading is level 4. Let's change that using {xml2}
xml2::xml_set_attr(ep1$headings[[1]], "level", "2")
ep1$head(20)
ep1$headings[[1]] # the first heading is now level 2
# write the file
ep1$write(fs::path_dir(ep1$path), format = "Rmd")
readLines(ep1$path, 20)


carpentries/pegboard documentation built on Nov. 13, 2024, 8:53 a.m.