-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathtar_quarto_files.R
144 lines (141 loc) · 5.42 KB
/
tar_quarto_files.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#' @title Quarto file detection
#' @export
#' @family Literate programming utilities
#' @description Detect the important files in a Quarto project.
#' @details This function is just a thin wrapper that interprets the output
#' of `quarto::quarto_inspect()` and returns what `tarchetypes` needs to
#' know about the current Quarto project or document.
#' @return A named list of important file paths in a Quarto project or document:
#' * `sources`: source files which may reference upstream target
#' dependencies in code chunks using `tar_load()`/`tar_read()`.
#' * `output`: output files that will be generated during
#' `quarto::quarto_render()`.
#' * `input`: pre-existing files required to render the project or document,
#' such as `_quarto.yml` and quarto extensions.
#' @inheritParams quarto::quarto_render
#' @param path Character of length 1, either the file path
#' to a Quarto source document or the directory path
#' to a Quarto project. Defaults to the Quarto project in the
#' current working directory.
#' @param profile Character of length 1, Quarto profile. If `NULL`,
#' the default profile will be used. Requires Quarto version 1.2 or higher.
#' See <https://quarto.org/docs/projects/profiles.html> for details.
#' @examples
#' lines <- c(
#' "---",
#' "title: source file",
#' "---",
#' "Assume these lines are in report.qmd.",
#' "```{r}",
#' "1 + 1",
#' "```"
#' )
#' path <- tempfile(fileext = ".qmd")
#' writeLines(lines, path)
#' # If Quarto is installed, run:
#' # tar_quarto_files(path)
tar_quarto_files <- function(path = ".", profile = NULL, quiet = TRUE) {
assert_quarto()
targets::tar_assert_scalar(path)
targets::tar_assert_chr(path)
targets::tar_assert_nzchar(path)
targets::tar_assert_path(path)
targets::tar_assert_scalar(profile %|||% ".")
targets::tar_assert_chr(profile %|||% ".")
targets::tar_assert_nzchar(profile %|||% ".")
out <- if_any(
fs::is_dir(path),
tar_quarto_files_project(path, profile, quiet),
tar_quarto_files_document(path, profile, quiet)
)
for (field in c("sources", "output", "input")) {
out[[field]] <- as.character(fs::path_rel(out[[field]]))
out[[field]] <- unique(sort(out[[field]]))
}
out
}
tar_quarto_files_document <- function(path, profile, quiet) {
info <- quarto::quarto_inspect(
input = path,
profile = profile,
quiet = quiet
)
out <- list()
# Collect data about source files.
out$sources <- tar_quarto_files_get_source_files(info$fileInformation)
# Collect data about output files.
output_dir <- info$project$config$project$`output-dir`
for (format in info$formats) {
out$output <- c(
out$output,
if_any(
is.null(output_dir),
file.path(dirname(path), format$pandoc$`output-file`),
file.path(output_dir, dirname(path), format$pandoc$`output-file`)
)
)
}
# Collect data about input files. As this is not a project, there doesn't
# exist the `info$files` key. However, we can include resources if present.
out$input <- as.character(info$resources)
out$input <- out$input[file.exists(out$input)]
out
}
tar_quarto_files_project <- function(path, profile, quiet) {
info <- quarto::quarto_inspect(
input = path,
profile = profile,
quiet = quiet
)
targets::tar_assert_nonempty(
info$config$project$`output-dir`,
paste(
"Quarto project must have an output-dir field",
"for compatibility with {tarchetypes}. Visit",
"quarto.org to learn how to set output-dir in _quarto.yml."
)
)
out <- list(output = file.path(path, info$config$project$`output-dir`))
# Collect data about source files.
out$sources <- tar_quarto_files_get_source_files(info$fileInformation)
# Detect input files like the config file (`_quarto.yml`) and resources like
# quarto extensions. Make sure in the end that these files exist.
out$input <- unlist(c(info$files$config, info$files$resources))
out$input <- out$input[file.exists(out$input)]
out
}
#' @title Get Source Files From Quarto Inspect
#' @keywords internal
#' @description Collects all files from the
#' `fileInformation` field that are used in the current report.
#' @details `fileInformation` contains a list of files. Each file entry contains
#' two data frames. The first, `includeMap`, contains a `source` column (files
#' that include other files, e.g. the main report file) and a `target` column
#' (files that get included by the `source` files). The `codeCells` data frame
#' contains all code cells from the files represented in `includeMap`.
#' @return A character vector of Quarto source files.
#' @param file_information The `fileInformation` element of the list
#' returned by `quarto::quarto_inspect()`.
tar_quarto_files_get_source_files <- function(file_information) {
out <- character(0)
for (myfile in names(file_information)) {
# Collect relevant source files. The files in `includeMap$target` are always
# relative to the main entry point of the report. Thus, we need to add the
# corresponding paths to the entries.
# We don't need to include the `source` column as all files are also present
# in `target` or are `myfile`.
out <- c(
out,
myfile,
file.path(
dirname(myfile),
file_information[[myfile]]$includeMap$target
)
)
}
# Check that these files actually exist.
out <- out[file.exists(out)]
# We don't need to call `unique` here on `out` as this happens on the main
# function.
out
}