Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Depends:
Imports:
cli,
fs,
htmltools,
jsonlite,
later,
processx,
Expand All @@ -40,6 +41,7 @@ Suggests:
ggplot2,
gt,
heatmaply,
kableExtra,
knitr,
palmerpenguins,
patchwork,
Expand All @@ -49,8 +51,9 @@ Suggests:
testthat (>= 3.1.7),
thematic,
tidyverse,
withr,
whoami
tinytable,
whoami,
withr
VignetteBuilder:
quarto
Config/testthat/edition: 3
Expand Down
10 changes: 10 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export(quarto_serve)
export(quarto_update_extension)
export(quarto_use_template)
export(quarto_version)
export(tbl_qmd_div)
export(tbl_qmd_div_base64)
export(tbl_qmd_div_raw)
export(tbl_qmd_span)
export(tbl_qmd_span_base64)
export(tbl_qmd_span_raw)
export(theme_brand_flextable)
export(theme_brand_ggplot2)
export(theme_brand_gt)
Expand All @@ -34,16 +40,20 @@ export(write_yaml_metadata_block)
import(rlang)
importFrom(cli,cli_abort)
importFrom(cli,cli_inform)
importFrom(htmltools,div)
importFrom(htmltools,span)
importFrom(jsonlite,fromJSON)
importFrom(later,later)
importFrom(processx,process)
importFrom(processx,run)
importFrom(rlang,caller_env)
importFrom(rlang,is_interactive)
importFrom(rmarkdown,relative_to)
importFrom(rstudioapi,isAvailable)
importFrom(rstudioapi,viewer)
importFrom(tools,vignetteEngine)
importFrom(utils,browseURL)
importFrom(xfun,base64_encode)
importFrom(xfun,env_option)
importFrom(yaml,as.yaml)
importFrom(yaml,write_yaml)
4 changes: 4 additions & 0 deletions R/quarto-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
## usethis namespace: start
#' @import rlang
#' @importFrom cli cli_inform
#' @importFrom htmltools div
#' @importFrom htmltools span
#' @importFrom rlang caller_env
#' @importFrom tools vignetteEngine
#' @importFrom xfun base64_encode
#' @importFrom xfun env_option
## usethis namespace: end
NULL
191 changes: 191 additions & 0 deletions R/table-helper.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#' Create Quarto Markdown HTML Elements for Tables
#'
#' Functions to wrap content in HTML spans or divs with data-qmd attributes for
#' Quarto processing within HTML tables. These functions are specifically designed
#' for use with HTML table packages like kableExtra, gt, or DT where you need
#' Quarto to process markdown content within table cells.
#'
#' @details
#' These functions create HTML elements with `data-qmd` or `data-qmd-base64`
#' attributes that Quarto processes during document rendering. The base64
#' encoding is recommended for content with special characters, quotes, or
#' complex formatting.
#'
#' Available functions:
#'
#' * `tbl_qmd_span()` and `tbl_qmd_div()` are the main functions with encoding options
#' * `tbl_qmd_span_base64()` and `tbl_qmd_div_base64()` explicitly use base64 encoding
#' * `tbl_qmd_span_raw()` and `tbl_qmd_div_raw()` explicitly use raw encoding
#'
#' This feature requires Quarto version 1.3 or higher with HTML format outputs.
#' For more information, see <https://quarto.org/docs/authoring/tables.html#html-tables>.
#'
#' @param content Character string of content to wrap. This can include Markdown,
#' LaTeX math, and Quarto shortcodes.
#' @param display Optional display text (if different from content). Useful for
#' fallback text when Quarto processing is not available or for better
#' accessibility.
#' @param use_base64 Logical, whether to base64 encode the content (recommended
#' for complex content with special characters or when content includes quotes)
#'
#' @return Character string containing the HTML element with appropriate data-qmd attributes
#'
#' @examples
#' # Basic span usage in table cells
#' tbl_qmd_span("**bold text**")
#' tbl_qmd_span("$\\alpha + \\beta$", display = "Greek formula")
#'
#' # Basic div usage in table cells
#' tbl_qmd_div("## Section Title\n\nContent here")
#' tbl_qmd_div("{{< video https://example.com >}}", display = "[Video content]")
#'
#' # Explicit encoding choices
#' tbl_qmd_span_base64("Complex $\\LaTeX$ content")
#' tbl_qmd_span_raw("Simple text")
#'
#' # Use with different HTML table packages
#' \dontrun{
#' # With kableExtra
#' library(kableExtra)
#' df <- data.frame(
#' math = c(tbl_qmd_span("$x^2$"), tbl_qmd_span("$\\sum_{i=1}^n x_i$")),
#' text = c(tbl_qmd_span("**Important**", "bold"), tbl_qmd_span("`code`", "code"))
#' )
#' kbl(df, format = "html", escape = FALSE) |> kable_styling()
#' }
#' @name tbl_qmd_elements
NULL


.validate_tbl_qmd_input <- function(
content,
display = NULL,
call = rlang::caller_env()
) {
if (!is.character(content) || length(content) != 1) {
cli::cli_abort("'content' must be a single character string", call = call)
}

if (!is.null(display) && (!is.character(display) || length(display) != 1)) {
cli::cli_abort(
"'display' must be NULL or a single character string",
call = call
)
}

invisible(TRUE)
}

#' @inheritParams tbl_qmd_elements
#' @param class Optional CSS class(es) to add to the element. While this works for
#' both span and div elements, it's more commonly used with div elements.
#' @param attrs Named list of additional HTML attributes to add to the element.
#' For example: `list(id = "my-element", title = "Tooltip text")`
#' @noRd
.tbl_qmd_element <- function(
tag,
content,
display,
use_base64,
class = NULL,
attrs = NULL
) {
.validate_tbl_qmd_input(content, display)

if (is.null(display)) {
display <- content
}

if (use_base64) {
encoded_content <- xfun::base64_encode(charToRaw(content))
attr_list <- list("data-qmd-base64" = encoded_content)
} else {
attr_list <- list("data-qmd" = content)
}

# Add class if provided
if (!is.null(class)) {
attr_list$class <- class
}

# Add any additional attributes
if (!is.null(attrs) && is.list(attrs) && length(attrs) > 0) {
attr_list <- c(attr_list, attrs)
}
# Create HTML element using htmltools
html_element <- if (tag == "div") {
do.call(htmltools::div, c(list(display, .noWS = "outside"), attr_list))
} else {
do.call(htmltools::span, c(list(display, .noWS = "outside"), attr_list))
}

# Convert to character string
as.character(html_element)
}

#' @rdname tbl_qmd_elements
#' @export
tbl_qmd_span <- function(
content,
display = NULL,
use_base64 = TRUE
) {
.tbl_qmd_element("span", content, display, use_base64)
}

#' @rdname tbl_qmd_elements
#' @export
tbl_qmd_div <- function(
content,
display = NULL,
use_base64 = TRUE
) {
.tbl_qmd_element("div", content, display, use_base64)
}
#' @rdname tbl_qmd_elements
#' @export
tbl_qmd_span_base64 <- function(
content,
display = NULL
) {
tbl_qmd_span(
content,
display,
use_base64 = TRUE
)
}

#' @rdname tbl_qmd_elements
#' @export
tbl_qmd_div_base64 <- function(
content,
display = NULL
) {
tbl_qmd_div(content, display, use_base64 = TRUE)
}

#' @rdname tbl_qmd_elements
#' @export
tbl_qmd_span_raw <- function(
content,
display = NULL
) {
tbl_qmd_span(
content,
display,
use_base64 = FALSE
)
}

#' @rdname tbl_qmd_elements
#' @export
tbl_qmd_div_raw <- function(
content,
display = NULL
) {
tbl_qmd_div(
content,
display,
use_base64 = FALSE
)
}
6 changes: 6 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ reference:
- starts_with("theme_colors")
- starts_with("theme_brand")

- title: "Table Helpers"
desc: >
These functions are used to help with tables in Quarto documents:
contents:
- starts_with("tbl_qmd_")

- title: "Miscellaneous"
desc: >
These functions are used to help with Quarto documents and projects:
Expand Down
84 changes: 84 additions & 0 deletions man/tbl_qmd_elements.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading