find_children()
returns the immediate children for any given Episode object.trace_children()
is used after processing in the context of a Lesson to trace the entire lineage from a source parent episode.
Arguments
- parent
an Episode or tinkr::yarn object (
trace_children()
requires anEpisode
object).- ancestor
an Episode object that is used to determine the parent path this also can be
NULL
.- lsn
a Lesson object that contains the
parent
and all its children.
Details
It is possible to define child documents
in knitr documents by using the child
attribute in code chunks. For
example, let's say we have a file called episodes/parent.Rmd
:
where files/the-child.Rmd
is relative to the build parent, in this case
it is episodes/parent.Rmd
. This is important
The find_children()
function will extract the immediate children from
a single Episode object (in this case, it will return
/path/to/episodes/files/the-child.Rmd
), but it will not detect any further
descendants. To detect the entire lineage, the Episode must be read in the
context of a Lesson (or processed with load_children()
).
This function is used during Episode initialisation to populate the
$children
element of the Episode
object, which lists paths to the
known children for further processing.
Tracing full lineages
It is possible for a child document to have further children defined, but
there is a caveat: The child document is going to be read from the context of
the root.dir
knitr option, which in sandpaper is set to be site/built
after the markdown contents and assets are copied over.
This is the first child. The following content is from the grandchild:
```{r child = "files/the-grandchild.md"}
```
When an Episode is read in the context of a Lesson, the children are
processed with load_children()
so that each document with children will have a
non-zero value of the $children
element. We recurse through the $children
element in the Lesson object to exhaust the search for the child documents.
The trace_children()
will return the entire lineage for a given parent
document. Which, in the case of the examples defined above would be:
/path/to/episodes/parent.Rmd
, /path/to/episodes/files/the-child.Rmd
,
and /path/to/episodes/files/the-grandchild.md
.
NOTE
For standard lessons, child documents are written relative to the directory
of the build parent document. Usually, these child documents will be in the
files
folder under their parent folder. Overview lessons are a little
different. For overview lessons (in The Workbench, these are lessons which
contain overview: true
in config.yaml), the child documents may point to
files/child.md
, but in reality, the child document is at the root of the
lesson ../files/child.md
. We correct for this by first checking that the
child documents exist and if they don't defaulting to the top of the lesson.
Examples
# needed for using internal functions: loading the namespace
pb <- asNamespace("pegboard")
# This example demonstrates a child document with another child document
# nested inside. First, we demonstrate how `find_children()` only returns
# the immediate children and then we demonstrate how the full lineage is
# extracted in the Lesson object.
#
# `find_children()` --------------------------------------------------------
ex <- lesson_fragment("sandpaper-fragment-with-child")
# The introduction has a single child document
intro <- tinkr::yarn$new(fs::path(ex, "episodes", "intro.Rmd"))
intro$head(21) # show the child document
#> ---
#> title: "Using RMarkdown"
#> teaching: 10
#> exercises: 2
#> ---
#>
#> :::::::::::::::::::::::::::::::::::::: questions
#>
#> - How do you write a lesson using RMarkdown and `{sandpaper}`?
#>
#> ::::::::::::::::::::::::::::::::::::::::::::::::
#>
#> ::::::::::::::::::::::::::::::::::::: objectives
#>
#> - Explain how to use markdown with the new lesson template
#> - Demonstrate how to include pieces of code, figures, and nested challenge blocks
#>
#> ::::::::::::::::::::::::::::::::::::::::::::::::
#>
#> ```{r cat-child, child="files/cat.Rmd"}
#> ```
pb$find_children(intro)
#> /home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/cat.Rmd
# this is identical to the `$children` element of an Episode object
ep <- Episode$new(fs::path(ex, "episodes", "intro.Rmd"))
ep$children
#> /home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/cat.Rmd
# Loading the child document reveals another child
child <- Episode$new(ep$children[[1]])
child$children
#> /home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/files/session.Rmd
child$show()
#> Here is a picture of a kitten:
#>
#> ![I hope you have a good day](https://placekitten.com/300/300){alt='a random cute kitten'}
#>
#> ```{r sessionInfo(), child="files/session.Rmd"}
#> ```
#>
# `trace_children()` -------------------------------------------------------
# In the context of the lesson, we can find all the descendants
lsn <- Lesson$new(ex, jekyll = FALSE)
pb$trace_children(ep, lsn)
#> [1] "/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/intro.Rmd"
#> [2] "/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/cat.Rmd"
#> [3] "/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/session.Rmd"
# This is the same as using the method of the same name in the Lesson object
# using the path to the episode
lsn$trace_lineage(ep$path)
#> [1] "/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/intro.Rmd"
#> [2] "/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/cat.Rmd"
#> [3] "/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/session.Rmd"
# show the children
purrr::walk(lsn$children, function(ep) {
message("----", ep$path, "----")
ep$show()
}
)
#> ----/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/cat.Rmd----
#> Here is a picture of a kitten:
#>
#> ![I hope you have a good day](https://placekitten.com/300/300){alt='a random cute kitten'}
#>
#> ```{r sessionInfo(), child="files/session.Rmd"}
#> ```
#>
#> ----/home/runner/work/_temp/Library/pegboard/sandpaper-fragment-with-child/episodes/files/session.Rmd----
#> <details>
#> <summary>Here is the sesion information for this build</summary>
#>
#> ```{r session-info}
#> sessioninfo::session_info()
#> ```
#>
#> </details>
#>