JSM 2024 - Portland
Duke University
parsermd
implements a C++ parser and abstract syntax tree (AST) for Quarto and R Markdown documents in R.
supports manipulating ASTs (filtering, editing, etc.)
ability to directly source and render ASTs
project started during covid to aide in the grading of student assignments in a large machine learning course
v0.1.3 is on CRAN, v0.2.0 with full Quarto support on GitHub (CRAN imminently)
Examples today will be with Quarto but all of this works the same with RMarkdown
hello.qmd
---
title: "Hello, Quarto"
format:
html:
self-contained: true
---
```{r}
#| label: load-packages
#| include: false
library(tidyverse)
library(palmerpenguins)
```
## Meet Quarto
Quarto enables you to weave together content and executable code into a finished document.
To learn more about Quarto see <https://quarto.org>.
## Meet the penguins
![](https://raw.githubusercontent.com/quarto-dev/quarto-web/main/docs/get-started/hello/rstudio/lter_penguins.png){style="float:right;" fig-alt="Illustration of three species of Palmer Archipelago penguins: Chinstrap, Gentoo, and Adelie. Artwork by @allison_horst." width="401"}
The `penguins` data from the [**palmerpenguins**](https://allisonhorst.github.io/palmerpenguins "palmerpenguins R package")
package contains size measurements for `{r} nrow(penguins)` penguins from three species
observed on three islands in the Palmer Archipelago, Antarctica.
The plot below shows the relationship between flipper and bill lengths of these penguins.
```{r}
#| label: plot-penguins
#| warning: false
#| echo: false
ggplot(penguins,
aes(x = flipper_length_mm, y = bill_length_mm)) +
geom_point(aes(color = species, shape = species)) +
scale_color_manual(values = c("darkorange","purple","cyan4")) +
labs(
title = "Flipper and bill length",
subtitle = "Dimensions for penguins at Palmer Station LTER",
x = "Flipper length (mm)", y = "Bill length (mm)",
color = "Penguin species", shape = "Penguin species"
) +
theme_minimal()
```
## Other Quarto features
### Fenced divs
:::{.callout-note}
Note that there are five types of callouts, including:
`note`, `tip`, `warning`, `caution`, and `important`.
:::
### Markdown code blocks
Some sample python code,
```python
import numpy as np
import matplotlib.pyplot as plt
r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
fig, ax = plt.subplots(
subplot_kw = {'projection': 'polar'}
)
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.grid(True)
plt.show()
```
### Short codes
Shortcodes are special markdown directives that generate various types of content,
{{< lipsum 1 >}}
├── YAML [2 fields]
├── Markdown [1 line]
├── Chunk [r, 1 option, 4 lines] - load-packages
├── Heading [h2] - Meet Quarto
├── Markdown [2 lines]
├── Heading [h2] - Meet the penguins
├── Markdown [8 lines]
├── Chunk [r, 3 options, 12 lines] - plot-penguins
├── Heading [h2] - Other Quarto features
├── Heading [h3] - Fenced divs
├── Open Fenced div [.callout-note]
├── Markdown [2 lines]
├── Close Fenced div
├── Heading [h3] - Markdown code blocks
├── Markdown [2 lines]
├── Code block [python, 12 lines]
├── Heading [h3] - Short codes
└── Markdown [3 lines]
├── YAML [2 fields]
├── Markdown [1 line]
├── Chunk [r, 1 option, 4 lines] - load-packages
├── Heading [h2] - Meet Quarto
│ └── Markdown [2 lines]
├── Heading [h2] - Meet the penguins
│ ├── Markdown [8 lines]
│ └── Chunk [r, 3 options, 12 lines] - plot-penguins
└── Heading [h2] - Other Quarto features
├── Heading [h3] - Fenced divs
│ ├── Open Fenced div [.callout-note]
│ │ └── Markdown [2 lines]
│ └── Close Fenced div
├── Heading [h3] - Markdown code blocks
│ ├── Markdown [2 lines]
│ └── Code block [python, 12 lines]
└── Heading [h3] - Short codes
└── Markdown [3 lines]
# A tibble: 18 × 5
sec_h2 sec_h3 type label ast
<chr> <chr> <chr> <chr> <rmd_ast>
1 <NA> <NA> rmd_yaml <NA> <yaml>
2 <NA> <NA> rmd_markdown <NA> <markdown>
3 <NA> <NA> rmd_chunk load… <chunk [r]>
4 Meet Quarto <NA> rmd_heading <NA> <heading [h2]>
5 Meet Quarto <NA> rmd_markdown <NA> <markdown>
6 Meet the penguins <NA> rmd_heading <NA> <heading [h2]>
7 Meet the penguins <NA> rmd_markdown <NA> <markdown>
8 Meet the penguins <NA> rmd_chunk plot… <chunk [r]>
9 Other Quarto features <NA> rmd_heading <NA> <heading [h2]>
10 Other Quarto features Fenced divs rmd_heading <NA> <heading [h3]>
11 Other Quarto features Fenced divs rmd_fenced_d… <NA> <rmd_fn__ [1]>
12 Other Quarto features Fenced divs rmd_markdown <NA> <markdown>
13 Other Quarto features Fenced divs rmd_fenced_d… <NA> <fdiv [close]>
14 Other Quarto features Markdown code blocks rmd_heading <NA> <heading [h3]>
15 Other Quarto features Markdown code blocks rmd_markdown <NA> <markdown>
16 Other Quarto features Markdown code blocks rmd_code_blo… <NA> <code block>
17 Other Quarto features Short codes rmd_heading <NA> <heading [h3]>
18 Other Quarto features Short codes rmd_markdown <NA> <markdown>
Use a CSS selector like approach to target specific nodes based on headings,
└── Heading [h2] - Other Quarto features
├── Heading [h3] - Markdown code blocks
│ ├── Markdown [2 lines]
│ └── Code block [python, 12 lines]
└── Heading [h3] - Short codes
└── Markdown [3 lines]
These ASTs can be converted back to Quarto documents at any point,
qmd |>
rmd_select(by_section(c("Other Quarto features", "*code blocks*"), keep_parents = FALSE)) |>
as_document() |>
cat(sep = "\n")
### Markdown code blocks
Some sample python code,
``` python
import numpy as np
import matplotlib.pyplot as plt
r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
fig, ax = plt.subplots(
subplot_kw = {'projection': 'polar'}
)
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.grid(True)
plt.show()
```
While a work in progress, we are adding additional helpers based on tidyselect
,
├── YAML [2 fields]
├── Chunk [r, 1 option, 4 lines] - load-packages
├── Heading [h2] - Meet Quarto
├── Heading [h2] - Meet the penguins
│ └── Chunk [r, 3 options, 12 lines] - plot-penguins
└── Heading [h2] - Other Quarto features
├── Heading [h3] - Fenced divs
│ ├── Open Fenced div [.callout-note]
│ └── Close Fenced div
├── Heading [h3] - Markdown code blocks
│ └── Code block [python, 12 lines]
└── Heading [h3] - Short codes
ASTs can also be directly rendered
repos/
├── hw01_team01
│ ├── README.md
│ ├── hw1.Rproj
│ └── hw1.qmd
├── hw01_team02
│ ├── README.md
│ ├── hw1.Rproj
│ └── hw1.qmd
├── hw01_team03
│ ├── README.md
│ ├── hw1.Rproj
│ └── hw1.qmd
├── hw01_team04
│ ├── README.md
│ ├── hw1.Rproj
│ └── hw1.qmd
└── hw01_team05
├── README.md
├── hw1.Rproj
└── hw1.qmd
├── YAML [2 fields]
├── Chunk [r, 0 options, 1 line] - load-packages
├── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [12 lines]
│ ├── Heading [h3] - Function
│ │ └── Chunk [r, 0 options, 32 lines] - fizzbuzz
│ └── Heading [h3] - Testing
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 9 lines] - good_inputs
│ └── Heading [h4] - Bad Inputs
│ ├── Chunk [r, 0 options, 4 lines] - throws_error
│ ├── Chunk [r, 1 option, 15 lines] - bad_inputs
│ └── Chunk [r, 0 options, 6 lines] - additional-test-cases
├── Heading [h2] - Task 2 - Re-Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [8 lines]
│ ├── Heading [h3] - Function
│ │ └── Chunk [r, 0 options, 52 lines] - fizzbuzz_s3
│ └── Heading [h3] - Testing
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 9 lines] - good_inputs_s3
│ └── Heading [h4] - Bad Inputs
│ ├── Chunk [r, 1 option, 15 lines] - bad_inputs_s3
│ └── Chunk [r, 0 options, 6 lines] - additional-test-cases-fizzbuzz_s3
└── Heading [h2] - Task 3 - Printing Secrets
├── Heading [h3] - Write up
│ └── Markdown [7 lines]
├── Heading [h3] - Function
│ ├── Chunk [r, 0 options, 6 lines] - secret
│ ├── Chunk [r, 0 options, 20 lines] - numeric_secret
│ ├── Chunk [r, 0 options, 4 lines] - char_secret
│ └── Chunk [r, 0 options, 50 lines] - print_secret
└── Heading [h3] - Testing
├── Chunk [r, 0 options, 9 lines] - unnamed-chunk-1
├── Heading [h4] - Valid Inputs
│ └── Chunk [r, 1 option, 11 lines] - good_inputs_secret
└── Heading [h4] - Bad Inputs
├── Chunk [r, 1 option, 12 lines] - bad_inputs_secret
└── Chunk [r, 0 options, 10 lines] - additional-test-cases-secret
├── YAML [2 fields]
└── Heading [h2] - Task 1 - Implement fizzbuzz
├── Heading [h3] - Write up
│ └── Markdown [12 lines]
├── Heading [h3] - Function
│ └── Chunk [r, 0 options, 32 lines] - fizzbuzz
└── Heading [h3] - Testing
├── Heading [h4] - Valid Inputs
│ └── Chunk [r, 1 option, 9 lines] - good_inputs
└── Heading [h4] - Bad Inputs
├── Chunk [r, 0 options, 4 lines] - throws_error
├── Chunk [r, 1 option, 15 lines] - bad_inputs
└── Chunk [r, 0 options, 6 lines] - additional-test-cases
hw1 |>
rmd_select(has_type("rmd_yaml"), by_section(c("Task 1*"))) |>
rmd_select(!by_section("Testing")) |>
rmd_ast_append(
rmd_chunk("tests", code = c(
"fizzbuzz(1:5)",
"fizzbuzz(5:1)",
"fizzbuzz(-1)"
), options = list(error = TRUE))
)
├── YAML [2 fields]
└── Heading [h2] - Task 1 - Implement fizzbuzz
├── Heading [h3] - Write up
│ └── Markdown [12 lines]
└── Heading [h3] - Function
├── Chunk [r, 0 options, 32 lines] - fizzbuzz
└── Chunk [r, 1 option, 3 lines] - tests
hw1 |>
rmd_select(has_type("rmd_yaml"), by_section(c("Task 1*"))) |>
rmd_select(!by_section("Testing")) |>
rmd_ast_append(
rmd_chunk("tests", code = c(
"fizzbuzz(1:5)",
"fizzbuzz(5:1)",
"fizzbuzz(-1)"
), options = list(error = TRUE))
) |>
render("hw1_task1")
[31m
processing file: hw1_task1.qmd
[39m
|
| | 0%
|
|............ | 20%
|
|........................ | 40% [fizzbuzz]
|
|................................... | 60%
|
|............................................... | 80% [tests]
|
|...........................................................| 100%
[31moutput file: hw1_task1.knit.md
[39m[1mpandoc [22m
to: html
output-file: hw1_task1.html
standalone: true
self-contained: true
section-divs: true
html-math-method: mathjax
wrap: none
default-image-extension: png
[1mmetadata[22m
document-css: false
link-citations: true
date-format: long
lang: en
title: Homework 1
Output created: hw1_task1.html
If you prefer to be able to interactively run the tests, you can use rmd_source()
to execute code from the ast in your environment,
This is a newish feature and still a bit experimental,
# A tibble: 5 × 3
name path ast
<chr> <fs::path> <list>
1 hw01_team01/hw1.qmd …Presentations/JSM2024/repos/hw01_team01/hw1.qmd <rmd_ast>
2 hw01_team02/hw1.qmd …Presentations/JSM2024/repos/hw01_team02/hw1.qmd <rmd_ast>
3 hw01_team03/hw1.qmd …Presentations/JSM2024/repos/hw01_team03/hw1.qmd <rmd_ast>
4 hw01_team04/hw1.qmd …Presentations/JSM2024/repos/hw01_team04/hw1.qmd <rmd_ast>
5 hw01_team05/hw1.qmd …Presentations/JSM2024/repos/hw01_team05/hw1.qmd <rmd_ast>
├── Heading [h1] - hw01_team01/hw1.qmd
│ ├── Chunk [r, 0 options, 1 line] - load-packages
│ ├── Heading [h2] - Task 1 - Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [12 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 32 lines] - fizzbuzz_1
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 9 lines] - good_inputs_1
│ │ └── Heading [h4] - Bad Inputs
│ │ ├── Chunk [r, 0 options, 4 lines] - throws_error_1
│ │ ├── Chunk [r, 1 option, 15 lines] - bad_inputs_1
│ │ └── Chunk [r, 0 options, 6 lines] - additional-test-cases
│ ├── Heading [h2] - Task 2 - Re-Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [8 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 52 lines] - fizzbuzz_s3_1
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 9 lines] - good_inputs_s3_1
│ │ └── Heading [h4] - Bad Inputs
│ │ ├── Chunk [r, 1 option, 15 lines] - bad_inputs_s3_1
│ │ └── Chunk [r, 0 options, 6 lines] - additional-test-cases-fizzbuzz_s3
│ └── Heading [h2] - Task 3 - Printing Secrets
│ ├── Heading [h3] - Write up
│ │ └── Markdown [7 lines]
│ ├── Heading [h3] - Function
│ │ ├── Chunk [r, 0 options, 6 lines] - secret_1
│ │ ├── Chunk [r, 0 options, 20 lines] - numeric_secret
│ │ ├── Chunk [r, 0 options, 4 lines] - char_secret
│ │ └── Chunk [r, 0 options, 50 lines] - print_secret_1
│ └── Heading [h3] - Testing
│ ├── Chunk [r, 0 options, 9 lines] - unnamed-chunk-1_1
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 11 lines] - good_inputs_secret_1
│ └── Heading [h4] - Bad Inputs
│ ├── Chunk [r, 1 option, 12 lines] - bad_inputs_secret_1
│ └── Chunk [r, 0 options, 10 lines] - additional-test-cases-secret
├── Heading [h1] - hw01_team02/hw1.qmd
│ ├── Heading [h2] - Task 1 - Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [2 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 35 lines] - fizzbuzz_2
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 11 lines] - good_inputs_2
│ │ └── Heading [h4] - Bad Inputs
│ │ ├── Chunk [r, 0 options, 4 lines] - throws_error_2
│ │ └── Chunk [r, 1 option, 17 lines] - bad_inputs_2
│ ├── Heading [h2] - Task 2 - Re-Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [2 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 50 lines] - fizzbuzz_s3_2
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 11 lines] - good_inputs_s3_2
│ │ └── Heading [h4] - Bad Inputs
│ │ └── Chunk [r, 1 option, 17 lines] - bad_inputs_s3_2
│ └── Heading [h2] - Task 3 - Printing Secrets
│ ├── Heading [h3] - Write up
│ │ └── Markdown [2 lines]
│ ├── Heading [h3] - Function
│ │ ├── Chunk [r, 0 options, 8 lines] - secret_2
│ │ ├── Chunk [r, 0 options, 30 lines] - print_secret_2
│ │ ├── Chunk [r, 0 options, 12 lines] - unnamed-chunk-1_2
│ │ ├── Chunk [r, 0 options, 12 lines] - print_character_helper
│ │ ├── Chunk [r, 0 options, 22 lines] - print_numeric_helper
│ │ └── Chunk [r, 0 options, 29 lines] - print_complex_helper
│ └── Heading [h3] - Testing
│ ├── Chunk [r, 0 options, 9 lines] - unnamed-chunk-2_1
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 13 lines] - good_inputs_secret_2
│ └── Heading [h4] - Bad Inputs
│ └── Chunk [r, 1 option, 16 lines] - bad_inputs_secret_2
├── Heading [h1] - hw01_team03/hw1.qmd
│ ├── Heading [h2] - Task 1 - Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [11 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 27 lines] - fizzbuzz_3
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 15 lines] - good_inputs_3
│ │ └── Heading [h4] - Bad Inputs
│ │ ├── Chunk [r, 0 options, 4 lines] - throws_error_3
│ │ └── Chunk [r, 1 option, 16 lines] - bad_inputs_3
│ ├── Heading [h2] - Task 2 - Re-Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [12 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 25 lines] - fizzbuzz_s3_3
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 10 lines] - good_inputs_s3_3
│ │ └── Heading [h4] - Bad Inputs
│ │ └── Chunk [r, 1 option, 18 lines] - bad_inputs_s3_3
│ └── Heading [h2] - Task 3 - Printing Secrets
│ ├── Heading [h3] - Write up
│ │ └── Markdown [19 lines]
│ ├── Heading [h3] - Function
│ │ ├── Chunk [r, 0 options, 6 lines] - secret_3
│ │ └── Chunk [r, 0 options, 97 lines] - print_secret_3
│ └── Heading [h3] - Testing
│ ├── Chunk [r, 0 options, 9 lines] - unnamed-chunk-1_3
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 14 lines] - good_inputs_secret_3
│ └── Heading [h4] - Bad Inputs
│ └── Chunk [r, 1 option, 12 lines] - bad_inputs_secret_3
├── Heading [h1] - hw01_team04/hw1.qmd
│ ├── Heading [h2] - Task 1 - Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [11 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 32 lines] - fizzbuzz_4
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 12 lines] - good-inputs-fizzbuzz
│ │ └── Heading [h4] - Bad Inputs
│ │ ├── Chunk [r, 0 options, 4 lines] - throws-error
│ │ └── Chunk [r, 1 option, 22 lines] - bad-inputs-fizzbuzz
│ ├── Heading [h2] - Task 2 - Re-Implement fizzbuzz
│ │ ├── Heading [h3] - Write up
│ │ │ └── Markdown [8 lines]
│ │ ├── Heading [h3] - Function
│ │ │ └── Chunk [r, 0 options, 43 lines] - fizzbuzz-s3
│ │ └── Heading [h3] - Testing
│ │ ├── Heading [h4] - Valid Inputs
│ │ │ └── Chunk [r, 1 option, 13 lines] - good-inputs-s3
│ │ └── Heading [h4] - Bad Inputs
│ │ └── Chunk [r, 1 option, 21 lines] - bad-inputs-s3
│ └── Heading [h2] - Task 3 - Printing Secrets
│ ├── Heading [h3] - Write up
│ │ └── Markdown [7 lines]
│ ├── Heading [h3] - Function
│ │ ├── Chunk [r, 0 options, 7 lines] - secret_4
│ │ └── Chunk [r, 0 options, 36 lines] - print-secret
│ └── Heading [h3] - Testing
│ ├── Chunk [r, 0 options, 10 lines] - print-secret-function
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 15 lines] - good-inputs-secret
│ └── Heading [h4] - Bad Inputs
│ └── Chunk [r, 1 option, 27 lines] - bad-inputs-secret
└── Heading [h1] - hw01_team05/hw1.qmd
├── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ ├── Markdown [4 lines]
│ │ └── Raw Attr Chunk [html, 5 lines]
│ ├── Heading [h3] - Function
│ │ └── Chunk [r, 0 options, 42 lines] - fizzbuzz_5
│ └── Heading [h3] - Testing
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 12 lines] - good_inputs_4
│ └── Heading [h4] - Bad Inputs
│ ├── Chunk [r, 0 options, 4 lines] - throws_error_4
│ └── Chunk [r, 1 option, 20 lines] - bad_inputs_4
├── Heading [h2] - Task 2 - Re-Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ ├── Markdown [4 lines]
│ │ └── Raw Attr Chunk [html, 5 lines]
│ ├── Heading [h3] - Function
│ │ └── Chunk [r, 0 options, 50 lines] - unnamed-chunk-1_4
│ └── Heading [h3] - Testing
│ ├── Heading [h4] - Valid Inputs
│ │ └── Chunk [r, 1 option, 12 lines] - good_inputs_s3_4
│ └── Heading [h4] - Bad Inputs
│ └── Chunk [r, 1 option, 20 lines] - bad_inputs_s3_4
└── Heading [h2] - Task 3 - Printing Secrets
├── Heading [h3] - Write up
│ ├── Markdown [12 lines]
│ └── Raw Attr Chunk [html, 5 lines]
├── Heading [h3] - Function
│ ├── Chunk [r, 0 options, 6 lines] - secret_5
│ ├── Chunk [r, 0 options, 9 lines] - makeAsterisks_helper
│ └── Chunk [r, 0 options, 69 lines] - print_secret_4
└── Heading [h3] - Testing
├── Chunk [r, 0 options, 9 lines] - unnamed-chunk-2_2
├── Heading [h4] - Valid Inputs
│ └── Chunk [r, 1 option, 13 lines] - good_inputs_secret_4
└── Heading [h4] - Bad Inputs
└── Chunk [r, 1 option, 18 lines] - bad_inputs_secret_4
# A tibble: 5 × 3
name path ast
<chr> <fs::path> <list>
1 hw01_team01/hw1.qmd …Presentations/JSM2024/repos/hw01_team01/hw1.qmd <rmd_ast>
2 hw01_team02/hw1.qmd …Presentations/JSM2024/repos/hw01_team02/hw1.qmd <rmd_ast>
3 hw01_team03/hw1.qmd …Presentations/JSM2024/repos/hw01_team03/hw1.qmd <rmd_ast>
4 hw01_team04/hw1.qmd …Presentations/JSM2024/repos/hw01_team04/hw1.qmd <rmd_ast>
5 hw01_team05/hw1.qmd …Presentations/JSM2024/repos/hw01_team05/hw1.qmd <rmd_ast>
├── Heading [h1] - hw01_team01/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [12 lines]
│ └── Heading [h3] - Function
│ └── Chunk [r, 0 options, 32 lines] - fizzbuzz_1
├── Heading [h1] - hw01_team02/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [2 lines]
│ └── Heading [h3] - Function
│ └── Chunk [r, 0 options, 35 lines] - fizzbuzz_2
├── Heading [h1] - hw01_team03/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [11 lines]
│ └── Heading [h3] - Function
│ └── Chunk [r, 0 options, 27 lines] - fizzbuzz_3
├── Heading [h1] - hw01_team04/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [11 lines]
│ └── Heading [h3] - Function
│ └── Chunk [r, 0 options, 32 lines] - fizzbuzz_4
└── Heading [h1] - hw01_team05/hw1.qmd
└── Heading [h2] - Task 1 - Implement fizzbuzz
├── Heading [h3] - Write up
│ ├── Markdown [4 lines]
│ └── Raw Attr Chunk [html, 5 lines]
└── Heading [h3] - Function
└── Chunk [r, 0 options, 42 lines] - fizzbuzz_5
(task1 = task1 |>
rmd_ast_append(
rmd_chunk("tests", code = c(
"fizzbuzz(1:5)",
"fizzbuzz(5:1)",
"fizzbuzz(-1)"
), options = list(error = TRUE))
) |>
as_ast() |>
rmd_ast_prepend(
rmd_chunk(
"load-libraries",
code = "library(tidyverse)",
options = list(message=FALSE)
)
)
)
task1 |> render("hw1_task1_coll2", quarto_args = c("--embed-resources"))
├── Chunk [r, 1 option, 1 line] - load-libraries
├── Heading [h1] - hw01_team01/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [12 lines]
│ └── Heading [h3] - Function
│ ├── Chunk [r, 0 options, 32 lines] - fizzbuzz_1
│ └── Chunk [r, 1 option, 3 lines] - tests_1
├── Heading [h1] - hw01_team02/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [2 lines]
│ └── Heading [h3] - Function
│ ├── Chunk [r, 0 options, 35 lines] - fizzbuzz_2
│ └── Chunk [r, 1 option, 3 lines] - tests_2
├── Heading [h1] - hw01_team03/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [11 lines]
│ └── Heading [h3] - Function
│ ├── Chunk [r, 0 options, 27 lines] - fizzbuzz_3
│ └── Chunk [r, 1 option, 3 lines] - tests_3
├── Heading [h1] - hw01_team04/hw1.qmd
│ └── Heading [h2] - Task 1 - Implement fizzbuzz
│ ├── Heading [h3] - Write up
│ │ └── Markdown [11 lines]
│ └── Heading [h3] - Function
│ ├── Chunk [r, 0 options, 32 lines] - fizzbuzz_4
│ └── Chunk [r, 1 option, 3 lines] - tests_4
└── Heading [h1] - hw01_team05/hw1.qmd
└── Heading [h2] - Task 1 - Implement fizzbuzz
├── Heading [h3] - Write up
│ ├── Markdown [4 lines]
│ └── Raw Attr Chunk [html, 5 lines]
└── Heading [h3] - Function
├── Chunk [r, 0 options, 42 lines] - fizzbuzz_5
└── Chunk [r, 1 option, 3 lines] - tests_5
The current version will be going up on CRAN imminently
More work on helper functions for rmd_select()
Implementing pipeable modifier functions
Thinking about more high-level user facing functions like rmd_template()
and rmd_check_template()
- see the vignette for more details
Building out and documenting any and all interesting use cases