From 2fc494e320065c6f0b108695c4705cc905522804 Mon Sep 17 00:00:00 2001 From: David C Hall Date: Tue, 31 Oct 2023 22:13:05 -0700 Subject: [PATCH] Document how to preserve length-1 vector Fixes #27 --- R/render.R | 9 ++++++++- man/render.Rd | 11 +++++++++-- vignettes/template-syntax.Rmd | 6 +++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/R/render.R b/R/render.R index 437ce2b..a80e074 100644 --- a/R/render.R +++ b/R/render.R @@ -7,6 +7,10 @@ #' * A path to a template file (use [fs::path()]). #' * A parsed template (use [parse_template()]). #' @param ... <[`dynamic-dots`][rlang::dyn-dots]> Data passed to the template. +#' +#' By default, a length-1 vector is passed as a scalar variable. Use [I()] to +#' declare that a vector should be passed as an array variable. This preserves +#' a length-1 vector as an array. #' @inheritParams parse #' @return String containing rendered template. #' @@ -18,7 +22,10 @@ #' # pass data as arguments #' render("Hello {{ name }}!", name = "world") #' -#' # pass data as list +#' # pass length-1 vector as array +#' render("Hello {{ name.0 }}!", name = I("world")) +#' +#' # pass data programmatically #' params <- list(name = "world") #' render("Hello {{ name }}!", !!!params) #' diff --git a/man/render.Rd b/man/render.Rd index c031f0f..2fa61ed 100644 --- a/man/render.Rd +++ b/man/render.Rd @@ -23,7 +23,11 @@ render(.x, ...) \item A parsed template (use \code{\link[=parse_template]{parse_template()}}). }} -\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> Data passed to the template.} +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> Data passed to the template. + +By default, a length-1 vector is passed as a scalar variable. Use \code{\link[=I]{I()}} to +declare that a vector should be passed as an array variable. This preserves +a length-1 vector as an array.} \item{.config}{The engine configuration. The default matches Jinja defaults, but you can use \code{\link[=jinjar_config]{jinjar_config()}} to customize things like syntax delimiters, @@ -39,7 +43,10 @@ Data is passed to a template to render the final document. # pass data as arguments render("Hello {{ name }}!", name = "world") -# pass data as list +# pass length-1 vector as array +render("Hello {{ name.0 }}!", name = I("world")) + +# pass data programmatically params <- list(name = "world") render("Hello {{ name }}!", !!!params) diff --git a/vignettes/template-syntax.Rmd b/vignettes/template-syntax.Rmd index edf30db..282c954 100644 --- a/vignettes/template-syntax.Rmd +++ b/vignettes/template-syntax.Rmd @@ -120,12 +120,16 @@ Although we pass R objects to `render()`, it is helpful to understand that these | Data frame | Array of objects | `{{ foo.1.bar }}` | You can use dot (`.`) notation to access data nested within a variable. -An array element is accessed by its numeric index (e.g. `foo.1`) and an object value is accessed by its key (e.g. `foo.bar`). +An array element is accessed by its numeric **zero-based** index (e.g. `foo.1`) and an object value is accessed by its key (e.g. `foo.bar`). **Note:** In R, the dot is a valid character in an object name (e.g. `my.data`). However, this causes ambiguity when accessing nested data values. For this reason, each dot is replaced with an underscore when the data is encoded as JSON (e.g. `my.data` becomes `my_data`). +**Note:** In R, a scalar is indistinguishable from a length-1 vector. +This creates an ambiguity when passing R data to the template, because template variables support both scalars and arrays. +You can explicitly pass a length-1 vector as an array using the `I()` operator (see `help("render")`). + The double-brace syntax is used to print the value of the variable (e.g. `{{ foo }}`). To use the variable in other contexts (e.g. control structures), then these braces are omitted (e.g. `{% for bar in foo %}`).