From 6af1d70f9ea9932de158e0f4835a15f079c12471 Mon Sep 17 00:00:00 2001 From: Vincent Arel-Bundock Date: Thu, 25 Jan 2024 08:11:23 -0500 Subject: [PATCH 1/5] bootstrap lines --- R/style_bootstrap.R | 15 ++++++++++++++- R/style_tabularray.R | 3 ++- R/style_tt.R | 41 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/R/style_bootstrap.R b/R/style_bootstrap.R index 5bede757..eca4eeb4 100644 --- a/R/style_bootstrap.R +++ b/R/style_bootstrap.R @@ -16,11 +16,15 @@ style_bootstrap <- function(x, fontsize = NULL, width = NULL, align = NULL, + line = NULL, + line_color = "black", + line_width = .1, colspan = NULL, indent = 0, bootstrap_class = "table", bootstrap_css = NULL, - bootstrap_css_rule = NULL) { + bootstrap_css_rule = NULL, + ...) { if (meta(x, "output") != "html") return(x) @@ -96,6 +100,15 @@ style_bootstrap <- function(x, settings$bootstrap <- paste(settings$bootstrap, sprintf("padding-left: %sem;", indent), sep = "") } + if (!is.null(line)) { + settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, line_color, "border-color: %s;") + } + + if (grepl("t", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-top: %s solid;") + if (grepl("b", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-bottom: %s solid;") + if (grepl("l", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-left: %s solid;") + if (grepl("r", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-right: %s solid;") + # unique IDs for each CSS style combination id <- sapply(unique(settings$bootstrap), function(k) get_id(stem = "tinytable_css_")) settings$id <- id[match(settings$bootstrap, names(id))] diff --git a/R/style_tabularray.R b/R/style_tabularray.R index 9aff03d5..850f1dc9 100644 --- a/R/style_tabularray.R +++ b/R/style_tabularray.R @@ -14,7 +14,8 @@ style_tabularray <- function(x, colspan = NULL, indent = 0, tabularray_inner = NULL, - tabularray_outer = NULL) { + tabularray_outer = NULL, + ...) { if (meta(x, "output") != "latex") return(x) diff --git a/R/style_tt.R b/R/style_tt.R index 39d81adf..5b5df55b 100644 --- a/R/style_tt.R +++ b/R/style_tt.R @@ -29,6 +29,14 @@ #' @param align A single character or a string with a number of characters equal to the number of columns in `j`. Valid characters include 'c' (center), 'l' (left), or 'r' (right). #' @param colspan Number of columns a cell should span. Can only be used if both `i` and `j` are of length 1. Must be an integer greater than 1. #' @param indent Text indentation in em units. Positive values only. +#' @param line String determines if solid lines (rules or borders) should be drawn around the cell, row, or column. +#' + "t": top +#' + "b": bottom +#' + "l": left +#' + "r": right +#' + Can be combined such as: "lbt" to draw borders at the left, bottom, and top. +#' @param line_color Color of the line. See the `color` argument for details. +#' @param line_width Width of the line in em units (default: 0.1). #' @param bootstrap_class String. A Bootstrap table class such as `"table"`, `"table table-dark"` or `"table table-dark table-hover"`. See the bootstrap documentation. #' @param bootstrap_css A vector of CSS style declarations to be applied (ex: `"font-weight: bold"`). Each element corresponds to a cell defined by `i` and `j`. #' @param bootstrap_css_rule A string with complete CSS rules that apply to the table class specified using the `theme` argument of the `tt()` function. @@ -61,6 +69,9 @@ style_tt <- function (x, align = NULL, colspan = NULL, indent = 0, + line = NULL, + line_color = "black", + line_width = 0.1, tabularray_inner = NULL, tabularray_outer = NULL, bootstrap_class = "table", @@ -86,6 +97,9 @@ style_tt <- function (x, align = align, colspan = colspan, indent = indent, + line = line, + line_color = line_color, + line_width = line_width, tabularray_inner = tabularray_inner, tabularray_outer = tabularray_outer, bootstrap_class = bootstrap_class, @@ -118,6 +132,9 @@ style_tt_lazy <- function (x, align, colspan, indent, + line, + line_color, + line_width, tabularray_inner, tabularray_outer, bootstrap_class, @@ -169,23 +186,27 @@ style_tt_lazy <- function (x, assert_style_tt( x = out, i = i, j = j, bold = bold, italic = italic, monospace = monospace, underline = underline, strikeout = strikeout, color = color, background = background, fontsize = fontsize, width = width, align = align, colspan = colspan, indent = indent, + line = line, line_color = line_color, line_width = line_width, tabularray_inner = tabularray_inner, tabularray_outer = tabularray_outer, bootstrap_css = bootstrap_css, bootstrap_css_rule = bootstrap_css_rule, bootstrap_class = bootstrap_class) out <- style_tabularray( x = out, i = i, j = j, bold = bold, italic = italic, monospace = monospace, underline = underline, strikeout = strikeout, color = color, background = background, fontsize = fontsize, width = width, align = align, colspan = colspan, indent = indent, - tabularray_inner = tabularray_inner, tabularray_outer = tabularray_outer) + tabularray_inner = tabularray_inner, tabularray_outer = tabularray_outer, + line = line, line_color = line_color, line_width = line_width) out <- style_bootstrap( x = out, i = i, j = j, bold = bold, italic = italic, monospace = monospace, underline = underline, strikeout = strikeout, color = color, background = background, fontsize = fontsize, width = width, align = align, colspan = colspan, indent = indent, - bootstrap_css = bootstrap_css, bootstrap_css_rule = bootstrap_css_rule, bootstrap_class = bootstrap_class) + bootstrap_css = bootstrap_css, bootstrap_css_rule = bootstrap_css_rule, bootstrap_class = bootstrap_class, + line = line, line_color = line_color, line_width = line_width) out <- style_grid( x = out, i = i, j = j, bold = bold, italic = italic, monospace = monospace, underline = underline, strikeout = strikeout, color = color, background = background, fontsize = fontsize, width = width, align = align, colspan = colspan, indent = indent, - bootstrap_css = bootstrap_css, bootstrap_css_rule = bootstrap_css_rule) + bootstrap_css = bootstrap_css, bootstrap_css_rule = bootstrap_css_rule, + line = line, line_color = line_color, line_width = line_width) return(out) } @@ -206,6 +227,9 @@ assert_style_tt <- function (x, align, colspan, indent, + line, + line_color, + line_width, tabularray_inner, tabularray_outer, bootstrap_class = NULL, @@ -225,10 +249,21 @@ assert_style_tt <- function (x, assert_logical(monospace) assert_logical(underline) assert_logical(strikeout) + assert_string(line, null.ok = TRUE) + assert_string(line_color, null.ok = FALSE) # black default + assert_numeric(line_width, len = 1, lower = 0, null.ok = FALSE) # 0.1 default assert_character(bootstrap_class, null.ok = TRUE) assert_character(bootstrap_css, null.ok = TRUE) assert_string(bootstrap_css_rule, null.ok = TRUE) + if (is.character(line)) { + line <- strsplit(line, split = "")[[1]] + if (!all(line %in% c("t", "b", "l", "r"))) { + msg <- "`line` must be a string of characters t, b, l, or r." + stop(msg, call. = FALSE) + } + } + ival <- if (is.null(i)) meta(x, "nrows") else i jval <- if (is.null(j)) meta(x, "ncols") else j From a4f6cda28b3ab97c1c6e9abcf318c49bfd7043f8 Mon Sep 17 00:00:00 2001 From: Vincent Arel-Bundock Date: Thu, 25 Jan 2024 09:29:32 -0500 Subject: [PATCH 2/5] line tabularray --- R/style_bootstrap.R | 11 +++++------ R/style_tabularray.R | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/R/style_bootstrap.R b/R/style_bootstrap.R index eca4eeb4..c24261f7 100644 --- a/R/style_bootstrap.R +++ b/R/style_bootstrap.R @@ -101,14 +101,13 @@ style_bootstrap <- function(x, } if (!is.null(line)) { - settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, line_color, "border-color: %s;") + tmp <- sprintf(": solid %s %s;", paste0(line_width, "em"), line_color) + if (grepl("t", line)) settings$bootstrap <- paste0(settings$bootstrap, " border-top", tmp) + if (grepl("b", line)) settings$bootstrap <- paste0(settings$bootstrap, " border-bottom", tmp) + if (grepl("l", line)) settings$bootstrap <- paste0(settings$bootstrap, " border-left", tmp) + if (grepl("r", line)) settings$bootstrap <- paste0(settings$bootstrap, " border-right", tmp) } - if (grepl("t", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-top: %s solid;") - if (grepl("b", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-bottom: %s solid;") - if (grepl("l", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-left: %s solid;") - if (grepl("r", line)) settings$bootstrap <- vectorize_bootstrap(settings$bootstrap, ".1em", "border-right: %s solid;") - # unique IDs for each CSS style combination id <- sapply(unique(settings$bootstrap), function(k) get_id(stem = "tinytable_css_")) settings$id <- id[match(settings$bootstrap, names(id))] diff --git a/R/style_tabularray.R b/R/style_tabularray.R index 850f1dc9..11802aa1 100644 --- a/R/style_tabularray.R +++ b/R/style_tabularray.R @@ -11,6 +11,9 @@ style_tabularray <- function(x, fontsize = NULL, width = NULL, align = NULL, + line = NULL, + line_color = "black", + line_width = .1, colspan = NULL, indent = 0, tabularray_inner = NULL, @@ -103,6 +106,7 @@ style_tabularray <- function(x, settings$tabularray <- trimws(gsub("\\s+", "", settings$tabularray)) settings$tabularray <- trimws(gsub(",+", ",", settings$tabularray)) + for (k in seq_len(nrow(settings))) { if (all(c("i", "j") %in% colnames(settings))) { spec <- sprintf("cell{%s}{%s}={%s}{%s},", settings$i[k], settings$j[k], span, settings$tabularray[k]) @@ -114,6 +118,36 @@ style_tabularray <- function(x, out <- tabularray_insert(out, content = spec, type = "inner") } + # Lines are not part of cellspec/rowspec/columnspec. Do this separately. + if (!is.null(line)) { + # TODO: handle hex colors + # browser() + iline <- jline <- NULL + if (grepl("t", line)) iline <- c(iline, ival + meta(x, "nhead")) + if (grepl("b", line)) iline <- c(iline, ival + meta(x, "nhead") + 1) + if (grepl("l", line)) jline <- c(jline, jval) + if (grepl("r", line)) jline <- c(jline, jval + 1) + iline <- unique(iline) + jline <- unique(jline) + line_width <- paste0(line_width, "em") + tmp <- sprintf( + "hline{%s}={%s}{solid, %s, %s},", + paste(iline, collapse = ","), + paste(jval, collapse = ","), + line_width, + line_color + ) + out <- tabularray_insert(out, content = tmp, type = "inner") + tmp <- sprintf( + "vline{%s}={%s}{solid, %s, %s},", + paste(jline, collapse = ","), + paste(ival + meta(x, "nhead"), collapse = ","), + line_width, + line_color + ) + out <- tabularray_insert(out, content = tmp, type = "inner") + } + out <- tabularray_insert(out, content = tabularray_inner, type = "inner") out <- tabularray_insert(out, content = tabularray_outer, type = "outer") From 4b1eaaf9d1511bcddc65b8956b156320470b99fa Mon Sep 17 00:00:00 2001 From: Vincent Arel-Bundock Date: Thu, 25 Jan 2024 09:51:00 -0500 Subject: [PATCH 3/5] tutorial --- vignettes/tutorial.qmd | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/vignettes/tutorial.qmd b/vignettes/tutorial.qmd index 3bc2ef1d..3134522a 100644 --- a/vignettes/tutorial.qmd +++ b/vignettes/tutorial.qmd @@ -574,6 +574,33 @@ tt(k, width = .7, theme = "void") |> fontsize = fs) ``` + +## Lines (borders) + +The `style_tt` function allows us to customize the borders that surround eacell of a table, as well horizontal and vertical rules. To control these lines, we use the `line`, `line_width`, and `line_color` arguments. Here's a brief overview of each of these arguments: + +- `line`: This argument specifies where solid lines should be drawn. It is a string that can consist of the following characters: + - `"t"`: Draw a line at the top of the cell, row, or column. + - `"b"`: Draw a line at the bottom of the cell, row, or column. + - `"l"`: Draw a line at the left side of the cell, row, or column. + - `"r"`: Draw a line at the right side of the cell, row, or column. + - You can combine these characters to draw lines on multiple sides, such as `"tbl"` to draw lines at the top, bottom, and left sides of a cell. +- `line_width`: This argument controls the width of the solid lines in em units (default: 0.1 em). You can adjust this value to make the lines thicker or thinner. +- `line_color`: Specifies the color of the solid lines. You can use color names, hexadecimal codes, or other color specifications to define the line color. + +Here is an example where we draw lines around every border ("t", "b", "l", and "r") of specified cells. + +```{r} +tt(x, theme = "void") |> + style_tt( + i = 0, + j = 1:4, + line = "tb", + line_width = 0.4, + line_color = "orange") +``` + + # Tiny plots and images The `plot_tt()` function can embed images and plots in a `tinytable`. We can insert images by specifying their paths and positions (`i`/`j`). From e36868729c56a814c76a479aa9e96f78a323ab4b Mon Sep 17 00:00:00 2001 From: Vincent Arel-Bundock Date: Thu, 25 Jan 2024 10:24:19 -0500 Subject: [PATCH 4/5] bugfix + tutorial --- R/style_tabularray.R | 36 ++++++++++++++++++++---------------- man/plot_tt.Rd | 6 +++--- man/style_tt.Rd | 16 ++++++++++++++++ vignettes/tutorial.qmd | 10 +++++----- 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/R/style_tabularray.R b/R/style_tabularray.R index 11802aa1..86bcf403 100644 --- a/R/style_tabularray.R +++ b/R/style_tabularray.R @@ -130,22 +130,26 @@ style_tabularray <- function(x, iline <- unique(iline) jline <- unique(jline) line_width <- paste0(line_width, "em") - tmp <- sprintf( - "hline{%s}={%s}{solid, %s, %s},", - paste(iline, collapse = ","), - paste(jval, collapse = ","), - line_width, - line_color - ) - out <- tabularray_insert(out, content = tmp, type = "inner") - tmp <- sprintf( - "vline{%s}={%s}{solid, %s, %s},", - paste(jline, collapse = ","), - paste(ival + meta(x, "nhead"), collapse = ","), - line_width, - line_color - ) - out <- tabularray_insert(out, content = tmp, type = "inner") + if (!is.null(iline)) { + tmp <- sprintf( + "hline{%s}={%s}{solid, %s, %s},", + paste(iline, collapse = ","), + paste(jval, collapse = ","), + line_width, + line_color + ) + out <- tabularray_insert(out, content = tmp, type = "inner") + } + if (!is.null(jline)) { + tmp <- sprintf( + "vline{%s}={%s}{solid, %s, %s},", + paste(jline, collapse = ","), + paste(ival + meta(x, "nhead"), collapse = ","), + line_width, + line_color + ) + out <- tabularray_insert(out, content = tmp, type = "inner") + } } out <- tabularray_insert(out, content = tabularray_inner, type = "inner") diff --git a/man/plot_tt.Rd b/man/plot_tt.Rd index 95181f3a..e4ec8957 100644 --- a/man/plot_tt.Rd +++ b/man/plot_tt.Rd @@ -35,7 +35,7 @@ images will be inserted in all columns.} \item See the tutorial on the \code{tinytable} website for more information. }} -\item{data}{Optional, a list of data frames to be used with a custom plotting function.} +\item{data}{a list of data frames or vectors to be used by the plotting functions in \code{fun}.} \item{color}{string Name of color to use for inline plots (passed to the \code{col} argument base \code{graphics} plots in \code{R}).} @@ -47,7 +47,7 @@ images will be inserted in all columns.} \item{images}{Character vector, the paths to the images to be inserted. Paths are relative to the main table file or Quarto (Rmarkdown) document.} -\item{assets}{Character, the directory to store generated assets.} +\item{assets}{Path to the directory where generated assets are stored. This path is relative to the location where a table is saved.} \item{...}{Extra arguments are passed to the function in \code{fun}. Important: Custom plotting functions must always have \code{...} as an argument.} } @@ -56,7 +56,7 @@ A modified tinytable object with images or plots inserted. } \description{ The \code{plot_tt()} function allows for the insertion of images and inline plots into -tinytable objects. This function can handle both local and web-based images. #' +tinytable objects. This function can handle both local and web-based images. } \details{ The \code{plot_tt()} can insert images and inline plots into tables. diff --git a/man/style_tt.Rd b/man/style_tt.Rd index 0f908502..be274a92 100644 --- a/man/style_tt.Rd +++ b/man/style_tt.Rd @@ -20,6 +20,9 @@ style_tt( align = NULL, colspan = NULL, indent = 0, + line = NULL, + line_color = "black", + line_width = 0.1, tabularray_inner = NULL, tabularray_outer = NULL, bootstrap_class = "table", @@ -73,6 +76,19 @@ style_tt( \item{indent}{Text indentation in em units. Positive values only.} +\item{line}{String determines if solid lines (rules or borders) should be drawn around the cell, row, or column. +\itemize{ +\item "t": top +\item "b": bottom +\item "l": left +\item "r": right +\item Can be combined such as: "lbt" to draw borders at the left, bottom, and top. +}} + +\item{line_color}{Color of the line. See the \code{color} argument for details.} + +\item{line_width}{Width of the line in em units (default: 0.1).} + \item{tabularray_inner}{A string that specifies the "inner" settings of a tabularray LaTeX table.} \item{tabularray_outer}{A string that specifies the "outer" settings of a tabularray LaTeX table.} diff --git a/vignettes/tutorial.qmd b/vignettes/tutorial.qmd index 3134522a..25235349 100644 --- a/vignettes/tutorial.qmd +++ b/vignettes/tutorial.qmd @@ -72,7 +72,7 @@ tt(x) |> save_tt("path/to/file.md") `save_tt()` can also return a string with the table in it, for further processing in `R`. In the first case, the table is printed to console with `cat()`. In the second case, it returns as a single string as an `R` object. -```{r} +```{r, eval = FALSE} tt(mtcars[1:10, 1:5]) |> group_tt( i = list( @@ -590,12 +590,12 @@ The `style_tt` function allows us to customize the borders that surround eacell Here is an example where we draw lines around every border ("t", "b", "l", and "r") of specified cells. -```{r} +```{r, eval = FALSE} tt(x, theme = "void") |> style_tt( - i = 0, - j = 1:4, - line = "tb", + i = 0:3, + j = 1:3, + line = "tblr", line_width = 0.4, line_color = "orange") ``` From 51cb230f95f55f867469007daed7e7e80f481a23 Mon Sep 17 00:00:00 2001 From: Vincent Arel-Bundock Date: Thu, 25 Jan 2024 10:44:00 -0500 Subject: [PATCH 5/5] cleanup --- R/style_tabularray.R | 20 +++++++++++--------- vignettes/tutorial.qmd | 13 +++++++++++-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/R/style_tabularray.R b/R/style_tabularray.R index 86bcf403..e21e745c 100644 --- a/R/style_tabularray.R +++ b/R/style_tabularray.R @@ -107,15 +107,17 @@ style_tabularray <- function(x, settings$tabularray <- trimws(gsub(",+", ",", settings$tabularray)) - for (k in seq_len(nrow(settings))) { - if (all(c("i", "j") %in% colnames(settings))) { - spec <- sprintf("cell{%s}{%s}={%s}{%s},", settings$i[k], settings$j[k], span, settings$tabularray[k]) - } else if ("i" %in% colnames(settings)) { - spec <- sprintf("row{%s}={%s},", settings$i[k], settings$tabularray[k]) - } else if ("j" %in% colnames(settings)) { - spec <- sprintf("column{%s}={%s},", settings$j[k], settings$tabularray[k]) - } - out <- tabularray_insert(out, content = spec, type = "inner") + if (!all(settings$tabularray == ",")) { + for (k in seq_len(nrow(settings))) { + if (all(c("i", "j") %in% colnames(settings))) { + spec <- sprintf("cell{%s}{%s}={%s}{%s},", settings$i[k], settings$j[k], span, settings$tabularray[k]) + } else if ("i" %in% colnames(settings)) { + spec <- sprintf("row{%s}={%s},", settings$i[k], settings$tabularray[k]) + } else if ("j" %in% colnames(settings)) { + spec <- sprintf("column{%s}={%s},", settings$j[k], settings$tabularray[k]) + } + out <- tabularray_insert(out, content = spec, type = "inner") + } } # Lines are not part of cellspec/rowspec/columnspec. Do this separately. diff --git a/vignettes/tutorial.qmd b/vignettes/tutorial.qmd index 25235349..057ba0dd 100644 --- a/vignettes/tutorial.qmd +++ b/vignettes/tutorial.qmd @@ -72,7 +72,7 @@ tt(x) |> save_tt("path/to/file.md") `save_tt()` can also return a string with the table in it, for further processing in `R`. In the first case, the table is printed to console with `cat()`. In the second case, it returns as a single string as an `R` object. -```{r, eval = FALSE} +```{r} tt(mtcars[1:10, 1:5]) |> group_tt( i = list( @@ -590,7 +590,7 @@ The `style_tt` function allows us to customize the borders that surround eacell Here is an example where we draw lines around every border ("t", "b", "l", and "r") of specified cells. -```{r, eval = FALSE} +```{r} tt(x, theme = "void") |> style_tt( i = 0:3, @@ -600,6 +600,15 @@ tt(x, theme = "void") |> line_color = "orange") ``` +And here is an example with horizontal rules: + +```{r} +tt(x, theme = "void") |> + style_tt(i = 0, line = "t", line_color = "orange", line_width = 0.4) |> + style_tt(i = 0, line = "b", line_color = "purple", line_width = 0.2) |> + style_tt(i = 4, line = "b", line_color = "orange", line_width = 0.4) +``` + # Tiny plots and images