diff --git a/R/group_tt.R b/R/group_tt.R index 05cc0056..ce198c6b 100644 --- a/R/group_tt.R +++ b/R/group_tt.R @@ -11,15 +11,16 @@ #' @param ... Other arguments are ignored. #' @return An object of class `tt` representing the table. #' @param indent integer number of `pt` to use when indenting the non-labelled rows. +#' @template limitations_word_markdown #' @details #' Warning: The `style_tt()` can normally be used to style the group headers, as expected, but that feature is not available for Markdown and Word tables. #' @examples #' #' # vector of row labels #' dat <- data.frame( -#' label = c("a", "a", "a", "b", "b", "c", "a", "a"), -#' x1 = rnorm(8), -#' x2 = rnorm(8)) +#' label = c("a", "a", "a", "b", "b", "c", "a", "a"), +#' x1 = rnorm(8), +#' x2 = rnorm(8)) #' tt(dat[, 2:3]) |> group_tt(i = dat$label) #' #' # named lists of labels @@ -51,7 +52,6 @@ #' group_tt(j = list("Hello" = 1:2, "World" = 3:4, "Hello" = 5:6)) |> #' group_tt(j = list("Foo" = 1:3, "Bar" = 4:6)) #' - group_tt <- function(x, i = NULL, j = NULL, indent = 1, ...) { # ... is important for ihead passing @@ -78,7 +78,7 @@ group_tt <- function(x, i = NULL, j = NULL, indent = 1, ...) { x@ngroupi <- length(i) x@nrow <- x@nrow + x@ngroupi x@group_i_idx <- as.numeric(i) - + if (isTRUE(indent > 0)) { idx_indent <- setdiff(seq_len(nrow(x)), i + seq_along(i) - 1) x <- style_tt(x, i = idx_indent, j = 1, indent = indent) diff --git a/R/style_tt.R b/R/style_tt.R index 742c4d00..d19e6d7d 100644 --- a/R/style_tt.R +++ b/R/style_tt.R @@ -3,14 +3,12 @@ #' @details #' This function applies styling to a table created by `tt()`. It allows customization of text style (bold, italic, monospace), text and background colors, font size, cell width, text alignment, column span, and indentation. The function also supports passing native instructions to LaTeX (tabularray) and HTML (bootstrap) formats. #' -#' Note: Markdown and Word tables only support these styles: italic, bold, strikeout. Moreover, the `style_tt()` function cannot be used to style headers inserted by the `group_tt()` function; instead, you should style the headers directly in the header definition using markdown syntax: `group_tt(i = list("*italic header*" = 2))`. These limitations are due to the fact that there is no markdown syntax for the other options, and that we create Word documents by converting a markdown table to .docx via the Pandoc software. -#' #' @param x A table object created by `tt()`. #' @param i Row indices where the styling should be applied. Can be a single value, a vector, or a logical matrix with the same number of rows and columns as `x`. `i=0` is the header, and negative values are higher level headers. Row indices refer to rows *after* the insertion of row labels by `group_tt()`, when applicable. #' @param j Column indices where the styling should be applied. Can be: #' + Integer vectors indicating column positions. #' + Character vector indicating column names. -#' + A single string specifying a Perl-style regular expression used to match column names. +#' + A single string specifying a Perl-style regular expression used to match column names. #' @param bold Logical; if `TRUE`, text is styled in bold. #' @param italic Logical; if `TRUE`, text is styled in italic. #' @param monospace Logical; if `TRUE`, text is styled in monospace font. @@ -24,7 +22,7 @@ #' - Hex code composed of # and 6 characters, ex: "#CC79A7". See the section below for instructions to add in LaTeX preambles. #' - Keywords: black, blue, brown, cyan, darkgray, gray, green, lightgray, lime, magenta, olive, orange, pink, purple, red, teal, violet, white, yellow. #' - Color blending using xcolor`, ex: `white!80!blue`, `green!20!red`. -#' - Color names with luminance levels from [the `ninecolors` package](https://mirror.quantum5.ca/CTAN/macros/latex/contrib/ninecolors/ninecolors.pdf) (ex: "azure4", "magenta8", "teal2", "gray1", "olive3"). +#' - Color names with luminance levels from [the `ninecolors` package](https://mirror.quantum5.ca/CTAN/macros/latex/contrib/ninecolors/ninecolors.pdf) (ex: "azure4", "magenta8", "teal2", "gray1", "olive3"). #' @param background Background color. Specified as a color name or hexadecimal code. Can be `NULL` for default color. #' @param fontsize Font size in em units. Can be `NULL` for default size. #' @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), 'r' (right), 'd' (decimal). Decimal alignment is only available in LaTeX via the `siunitx` package. The width of columns is determined by the maximum number of digits to the left and to the right in all cells specified by `i` and `j`. @@ -32,7 +30,7 @@ #' @param colspan Number of columns a cell should span. `i` and `j` must be of length 1. #' @param rowspan Number of rows a cell should span. `i` and `j` must be of length 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. +#' @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 @@ -41,38 +39,39 @@ #' @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 finalize A function applied to the table object at the very end of table-building, for post-processing. For example, the function could use regular expressions to add LaTeX commands to the text version of the table hosted in `x@table_string`, or it could programmatically change the caption in `x@caption`. -#' @param bootstrap_css Character vector. CSS style declarations to be applied to every cell defined by `i` and `j` (ex: `"font-weight: bold"`). -#' @param bootstrap_class String. Bootstrap table class such as `"table"`, `"table table-dark"` or `"table table-dark table-hover"`. See the bootstrap documentation. +#' @param bootstrap_css Character vector. CSS style declarations to be applied to every cell defined by `i` and `j` (ex: `"font-weight: bold"`). +#' @param bootstrap_class String. Bootstrap table class such as `"table"`, `"table table-dark"` or `"table table-dark table-hover"`. See the bootstrap documentation. #' @param bootstrap_css_rule String. Complete CSS rules (with curly braces, semicolon, etc.) that apply to the table class specified by the `bootstrap_class` argument. -#' @param tabularray_inner A string that specifies the "inner" settings of a tabularray LaTeX table. +#' @param tabularray_inner A string that specifies the "inner" settings of a tabularray LaTeX table. #' @param tabularray_outer A string that specifies the "outer" settings of a tabularray LaTeX table. -#' @param output Apply style only to the output format specified by this argument. `NULL` means that we apply to all formats. +#' @param output Apply style only to the output format specified by this argument. `NULL` means that we apply to all formats. #' @param ... extra arguments are ignored #' @return An object of class `tt` representing the table. +#' @template limitations_word_markdown #' @export #' @examplesIf knitr::is_html_output() #' @examples #' if (knitr::is_html_output()) options(tinytable_print_output = "html") -#' +#' #' library(tinytable) -#' +#' #' tt(mtcars[1:5, 1:6]) -#' +#' #' # Alignment -#' tt(mtcars[1:5, 1:6]) |> +#' tt(mtcars[1:5, 1:6]) |> #' style_tt(j = 1:5, align = "lcccr") -#' +#' #' # Colors and styles -#' tt(mtcars[1:5, 1:6]) |> +#' tt(mtcars[1:5, 1:6]) |> #' style_tt(i = 2:3, background = "black", color = "orange", bold = TRUE) -#' +#' #' # column selection with `j`` -#' tt(mtcars[1:5, 1:6]) |> +#' tt(mtcars[1:5, 1:6]) |> #' style_tt(j = 5:6, background = "pink") -#' +#' #' tt(mtcars[1:5, 1:6]) |> #' style_tt(j = "drat|wt", background = "pink") -#' +#' #' tt(mtcars[1:5, 1:6]) |> #' style_tt(j = c("drat", "wt"), background = "pink") #' @@ -81,27 +80,27 @@ #' i = 2, j = 2, #' colspan = 3, #' rowspan = 2, -#' align="c", +#' align = "c", #' alignv = "m", #' color = "white", #' background = "black", #' bold = TRUE) -#' +#' #' tt(mtcars[1:5, 1:6], theme = "void") |> #' style_tt( -#' i=0:3, -#' j=1:3, -#' line="tblr", -#' line_width=0.4, -#' line_color="teal") -#' +#' i = 0:3, +#' j = 1:3, +#' line = "tblr", +#' line_width = 0.4, +#' line_color = "teal") +#' #' tt(mtcars[1:5, 1:6], theme = "bootstrap") |> -#' style_tt( -#' i = c(2,5), -#' j = 3, -#' strikeout = TRUE, -#' fontsize = 0.7) -#' +#' style_tt( +#' i = c(2, 5), +#' j = 3, +#' strikeout = TRUE, +#' fontsize = 0.7) +#' #' tt(mtcars[1:5, 1:6]) |> #' style_tt(bootstrap_class = "table table-dark table-hover") #' @@ -119,252 +118,248 @@ #' tt(mtcars[1:5, 1:4], theme = "void") |> #' style_tt(tabularray_inner = inner) #' -style_tt <- function (x, - i = NULL, - j = NULL, - bold = FALSE, - italic = FALSE, - monospace = FALSE, - underline = FALSE, - strikeout = FALSE, - color = NULL, - background = NULL, - fontsize = NULL, - align = NULL, - alignv = NULL, - colspan = NULL, - rowspan = NULL, - indent = NULL, - line = NULL, - line_color = "black", - line_width = 0.1, - finalize = NULL, - tabularray_inner = NULL, - tabularray_outer = NULL, - bootstrap_class = NULL, - bootstrap_css = NULL, - bootstrap_css_rule = NULL, - output = NULL, - ...) { - - out <- x +style_tt <- function(x, + i = NULL, + j = NULL, + bold = FALSE, + italic = FALSE, + monospace = FALSE, + underline = FALSE, + strikeout = FALSE, + color = NULL, + background = NULL, + fontsize = NULL, + align = NULL, + alignv = NULL, + colspan = NULL, + rowspan = NULL, + indent = NULL, + line = NULL, + line_color = "black", + line_width = 0.1, + finalize = NULL, + tabularray_inner = NULL, + tabularray_outer = NULL, + bootstrap_class = NULL, + bootstrap_css = NULL, + bootstrap_css_rule = NULL, + output = NULL, + ...) { + out <- x - assert_choice(alignv, c("t", "m", "b"), null.ok = TRUE) + assert_choice(alignv, c("t", "m", "b"), null.ok = TRUE) - 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, align = align, - colspan = colspan, rowspan = rowspan, 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) + 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, align = align, + colspan = colspan, rowspan = rowspan, 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) - if (!is.null(bootstrap_class)) { - out@bootstrap_class <- bootstrap_class - } - if (!is.null(bootstrap_css_rule)) { - out@bootstrap_css_rule <- bootstrap_css_rule - } + if (!is.null(bootstrap_class)) { + out@bootstrap_class <- bootstrap_class + } + if (!is.null(bootstrap_css_rule)) { + out@bootstrap_css_rule <- bootstrap_css_rule + } - sanity_align(align, i) + sanity_align(align, i) - assert_choice(output, c("typst", "latex", "html", "markdown", "gfm"), null.ok = TRUE) + assert_choice(output, c("typst", "latex", "html", "markdown", "gfm"), null.ok = TRUE) - if ("width" %in% names(list(...))) { - stop("The `width` argument is now in the `tt()` function.", call. = FALSE) - } + if ("width" %in% names(list(...))) { + stop("The `width` argument is now in the `tt()` function.", call. = FALSE) + } - # i is a logical matrix mask - if (is.matrix(i) && is.logical(i) && nrow(i) == nrow(x) && ncol(i) == ncol(x)) { - assert_null(j) - settings <- which(i == TRUE, arr.ind = TRUE) - settings <- stats::setNames(data.frame(settings), c("i", "j")) - } else { - ival <- sanitize_i(i, x) - jval <- sanitize_j(j, x) - # order may be important for recycling - settings <- expand.grid(i = ival, j = jval, tabularray = "") - if (is.null(i) && !is.null(j)) { - settings <- settings[order(settings$i, settings$j), ] - } + # i is a logical matrix mask + if (is.matrix(i) && is.logical(i) && nrow(i) == nrow(x) && ncol(i) == ncol(x)) { + assert_null(j) + settings <- which(i == TRUE, arr.ind = TRUE) + settings <- stats::setNames(data.frame(settings), c("i", "j")) + } else { + ival <- sanitize_i(i, x) + jval <- sanitize_j(j, x) + # order may be important for recycling + settings <- expand.grid(i = ival, j = jval, tabularray = "") + if (is.null(i) && !is.null(j)) { + settings <- settings[order(settings$i, settings$j), ] } + } - settings[["color"]] <- if (is.null(color)) NA else as.vector(color) - settings[["background"]] <- if (is.null(background)) NA else as.vector(background) - settings[["fontsize"]] <- if (is.null(fontsize)) NA else as.vector(fontsize) - settings[["alignv"]] <- if (is.null(alignv)) NA else alignv - settings[["line"]] <- if (is.null(line)) NA else line - settings[["line_color"]] <- if (is.null(line)) NA else line_color - settings[["line_width"]] <- if (is.null(line)) NA else line_width - settings[["bold"]] <- bold - settings[["italic"]] <- italic - settings[["monospace"]] <- monospace - settings[["strikeout"]] <- strikeout - settings[["underline"]] <- underline - settings[["indent"]] <- if (is.null(indent)) NA else as.vector(indent) - settings[["colspan"]] <- if (is.null(colspan)) NA else colspan - settings[["rowspan"]] <- if (is.null(rowspan)) NA else rowspan - settings[["bootstrap_css_rule"]] <- if (!is.null(bootstrap_css_rule)) bootstrap_css_rule else NA - settings[["bootstrap_css"]] <- if (!is.null(bootstrap_css)) bootstrap_css else NA - settings[["tabularray_inner"]] <- if (!is.null(tabularray_inner)) tabularray_inner else NA - settings[["tabularray_outer"]] <- if (!is.null(tabularray_outer)) tabularray_outer else NA + settings[["color"]] <- if (is.null(color)) NA else as.vector(color) + settings[["background"]] <- if (is.null(background)) NA else as.vector(background) + settings[["fontsize"]] <- if (is.null(fontsize)) NA else as.vector(fontsize) + settings[["alignv"]] <- if (is.null(alignv)) NA else alignv + settings[["line"]] <- if (is.null(line)) NA else line + settings[["line_color"]] <- if (is.null(line)) NA else line_color + settings[["line_width"]] <- if (is.null(line)) NA else line_width + settings[["bold"]] <- bold + settings[["italic"]] <- italic + settings[["monospace"]] <- monospace + settings[["strikeout"]] <- strikeout + settings[["underline"]] <- underline + settings[["indent"]] <- if (is.null(indent)) NA else as.vector(indent) + settings[["colspan"]] <- if (is.null(colspan)) NA else colspan + settings[["rowspan"]] <- if (is.null(rowspan)) NA else rowspan + settings[["bootstrap_css_rule"]] <- if (!is.null(bootstrap_css_rule)) bootstrap_css_rule else NA + settings[["bootstrap_css"]] <- if (!is.null(bootstrap_css)) bootstrap_css else NA + settings[["tabularray_inner"]] <- if (!is.null(tabularray_inner)) tabularray_inner else NA + settings[["tabularray_outer"]] <- if (!is.null(tabularray_outer)) tabularray_outer else NA - if (!is.null(align)) { - if (nchar(align) == length(jval)) { - align_string <- strsplit(align, "")[[1]] - if (!all(align_string %in% c("c", "l", "r", "d"))) { - msg <- "`align` must be characters c, l, r, or d." - stop(msg, call. = FALSE) - } - align_string <- data.frame(j = jval, align = align_string) - settings <- merge(settings, align_string, by = "j", all.x = TRUE) - } else if (nchar(align) == 1) { - assert_choice(align, c("c", "l", "r", "d")) - align_string <- data.frame(j = jval, align = align) - settings <- merge(settings, align_string, by = "j", all.x = TRUE) - } else { - msg <- sprintf("`align` must be a single character or a string of length %s.", length(jval)) - stop(msg, call. = FALSE) - } + if (!is.null(align)) { + if (nchar(align) == length(jval)) { + align_string <- strsplit(align, "")[[1]] + if (!all(align_string %in% c("c", "l", "r", "d"))) { + msg <- "`align` must be characters c, l, r, or d." + stop(msg, call. = FALSE) + } + align_string <- data.frame(j = jval, align = align_string) + settings <- merge(settings, align_string, by = "j", all.x = TRUE) + } else if (nchar(align) == 1) { + assert_choice(align, c("c", "l", "r", "d")) + align_string <- data.frame(j = jval, align = align) + settings <- merge(settings, align_string, by = "j", all.x = TRUE) } else { - settings[["align"]] <- NA + msg <- sprintf("`align` must be a single character or a string of length %s.", length(jval)) + stop(msg, call. = FALSE) } + } else { + settings[["align"]] <- NA + } - empty <- settings[, 4:ncol(settings)] - empty <- sapply(empty, function(x) is.na(x) | (is.logical(x) && !any(x))) - if (nrow(settings) == 1) { - empty <- all(empty) - settings <- settings[!empty, , drop = FALSE] - } else { - empty <- apply(empty, 1, all) - settings <- settings[!empty, , drop = FALSE] - } + empty <- settings[, 4:ncol(settings)] + empty <- sapply(empty, function(x) is.na(x) | (is.logical(x) && !any(x))) + if (nrow(settings) == 1) { + empty <- all(empty) + settings <- settings[!empty, , drop = FALSE] + } else { + empty <- apply(empty, 1, all) + settings <- settings[!empty, , drop = FALSE] + } - if (nrow(out@style) > 0 && nrow(settings) > 0 && ncol(out@style) != ncol(settings)) { - a <- out@style - b <- settings - if (!"tabularray" %in% colnames(a)) a$tabularray <- "" - if (!"tabularray" %in% colnames(b)) b$tabularray <- "" - settings <- rbind(a, b[, colnames(a)]) - out@style <- unique(settings) - } else if (nrow(settings) > 0) { - out@style <- rbind(out@style, settings) - } + if (nrow(out@style) > 0 && nrow(settings) > 0 && ncol(out@style) != ncol(settings)) { + a <- out@style + b <- settings + if (!"tabularray" %in% colnames(a)) a$tabularray <- "" + if (!"tabularray" %in% colnames(b)) b$tabularray <- "" + settings <- rbind(a, b[, colnames(a)]) + out@style <- unique(settings) + } else if (nrow(settings) > 0) { + out@style <- rbind(out@style, settings) + } - ## issue #759: reuse object with different styles across RevealJS slides requires new ID every time style_tt is called - # This is a very bad idea. Breaks a ton of things. We need unique IDs. - # out@id <- get_id("tinytable_") + ## issue #759: reuse object with different styles across RevealJS slides requires new ID every time style_tt is called + # This is a very bad idea. Breaks a ton of things. We need unique IDs. + # out@id <- get_id("tinytable_") - assert_function(finalize, null.ok = TRUE) - if (is.function(finalize)) { - out@lazy_finalize <- c(out@lazy_finalize, list(finalize)) - } + assert_function(finalize, null.ok = TRUE) + if (is.function(finalize)) { + out@lazy_finalize <- c(out@lazy_finalize, list(finalize)) + } - return(out) + return(out) } -assert_style_tt <- function (x, - i, - j, - bold, - italic, - monospace, - underline, - strikeout, - color, - background, - fontsize, - align, - colspan, - rowspan, - indent, - line, - line_color, - line_width, - tabularray_inner, - tabularray_outer, - bootstrap_class = NULL, - bootstrap_css = NULL, - bootstrap_css_rule = NULL) { +assert_style_tt <- function(x, + i, + j, + bold, + italic, + monospace, + underline, + strikeout, + color, + background, + fontsize, + align, + colspan, + rowspan, + indent, + line, + line_color, + line_width, + tabularray_inner, + tabularray_outer, + bootstrap_class = NULL, + bootstrap_css = NULL, + bootstrap_css_rule = NULL) { + assert_integerish(colspan, len = 1, lower = 2, null.ok = TRUE) + assert_integerish(rowspan, len = 1, lower = 2, null.ok = TRUE) + assert_numeric(indent, len = 1, lower = 0, null.ok = TRUE) + assert_character(background, null.ok = TRUE) + assert_character(color, null.ok = TRUE) + assert_numeric(fontsize, null.ok = TRUE) + assert_logical(bold) + assert_logical(italic) + 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) - assert_integerish(colspan, len = 1, lower = 2, null.ok = TRUE) - assert_integerish(rowspan, len = 1, lower = 2, null.ok = TRUE) - assert_numeric(indent, len = 1, lower = 0, null.ok = TRUE) - assert_character(background, null.ok = TRUE) - assert_character(color, null.ok = TRUE) - assert_numeric(fontsize, null.ok = TRUE) - assert_logical(bold) - assert_logical(italic) - 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) - } + 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 <- sanitize_i(i, x) - jval <- sanitize_j(j, x) - inull <- isTRUE(attr(ival, "null")) - jnull <- isTRUE(attr(jval, "null")) + ival <- sanitize_i(i, x) + jval <- sanitize_j(j, x) + inull <- isTRUE(attr(ival, "null")) + jnull <- isTRUE(attr(jval, "null")) - # 1 - if (inull && jnull) { - assert_length(color, len = 1, null.ok = TRUE) - assert_length(background, len = 1, null.ok = TRUE) - assert_length(fontsize, len = 1, null.ok = TRUE) - assert_length(bold, len = 1) - assert_length(italic, len = 1) - assert_length(monospace, len = 1) - assert_length(underline, len = 1) - assert_length(strikeout, len = 1) + # 1 + if (inull && jnull) { + assert_length(color, len = 1, null.ok = TRUE) + assert_length(background, len = 1, null.ok = TRUE) + assert_length(fontsize, len = 1, null.ok = TRUE) + assert_length(bold, len = 1) + assert_length(italic, len = 1) + assert_length(monospace, len = 1) + assert_length(underline, len = 1) + assert_length(strikeout, len = 1) # 1 or #rows - } else if (!inull && jnull) { - assert_length(color, len = c(1, length(ival)), null.ok = TRUE) - assert_length(background, len = c(1, length(ival)), null.ok = TRUE) - assert_length(fontsize, len = c(1, length(ival)), null.ok = TRUE) - assert_length(bold, len = c(1, length(ival))) - assert_length(italic, len = c(1, length(ival))) - assert_length(monospace, len = c(1, length(ival))) - assert_length(underline, len = c(1, length(ival))) - assert_length(strikeout, len = c(1, length(ival))) + } else if (!inull && jnull) { + assert_length(color, len = c(1, length(ival)), null.ok = TRUE) + assert_length(background, len = c(1, length(ival)), null.ok = TRUE) + assert_length(fontsize, len = c(1, length(ival)), null.ok = TRUE) + assert_length(bold, len = c(1, length(ival))) + assert_length(italic, len = c(1, length(ival))) + assert_length(monospace, len = c(1, length(ival))) + assert_length(underline, len = c(1, length(ival))) + assert_length(strikeout, len = c(1, length(ival))) # 1 or #cols - } else if (inull && !jnull) { - assert_length(color, len = c(1, length(jval)), null.ok = TRUE) - assert_length(background, len = c(1, length(jval)), null.ok = TRUE) - assert_length(fontsize, len = c(1, length(jval)), null.ok = TRUE) - assert_length(bold, len = c(1, length(jval))) - assert_length(italic, len = c(1, length(jval))) - assert_length(monospace, len = c(1, length(jval))) - assert_length(underline, len = c(1, length(jval))) - assert_length(strikeout, len = c(1, length(jval))) + } else if (inull && !jnull) { + assert_length(color, len = c(1, length(jval)), null.ok = TRUE) + assert_length(background, len = c(1, length(jval)), null.ok = TRUE) + assert_length(fontsize, len = c(1, length(jval)), null.ok = TRUE) + assert_length(bold, len = c(1, length(jval))) + assert_length(italic, len = c(1, length(jval))) + assert_length(monospace, len = c(1, length(jval))) + assert_length(underline, len = c(1, length(jval))) + assert_length(strikeout, len = c(1, length(jval))) # 1 or #cells - } else if (!inull && !jnull) { - assert_length(color, len = c(1, length(ival) * length(jval)), null.ok = TRUE) - assert_length(background, len = c(1, length(ival) * length(jval)), null.ok = TRUE) - assert_length(fontsize, len = c(1, length(ival) * length(jval)), null.ok = TRUE) - assert_length(bold, len = c(1, length(ival) * length(jval))) - assert_length(italic, len = c(1, length(ival) * length(jval))) - assert_length(monospace, len = c(1, length(ival) * length(jval))) - assert_length(underline, len = c(1, length(ival) * length(jval))) - assert_length(strikeout, len = c(1, length(ival) * length(jval))) - } + } else if (!inull && !jnull) { + assert_length(color, len = c(1, length(ival) * length(jval)), null.ok = TRUE) + assert_length(background, len = c(1, length(ival) * length(jval)), null.ok = TRUE) + assert_length(fontsize, len = c(1, length(ival) * length(jval)), null.ok = TRUE) + assert_length(bold, len = c(1, length(ival) * length(jval))) + assert_length(italic, len = c(1, length(ival) * length(jval))) + assert_length(monospace, len = c(1, length(ival) * length(jval))) + assert_length(underline, len = c(1, length(ival) * length(jval))) + assert_length(strikeout, len = c(1, length(ival) * length(jval))) + } } - - diff --git a/R/tt.R b/R/tt.R index ed75619b..376b3671 100644 --- a/R/tt.R +++ b/R/tt.R @@ -15,8 +15,8 @@ #' @param x A data frame or data table to be rendered as a table. #' @param digits Number of significant digits to keep for numeric variables. When `digits` is an integer, `tt()` calls `format_tt(x, digits = digits)` before proceeding to draw the table. Note that this will apply all default argument values of `format_tt()`, such as replacing `NA` by "". Users who need more control can use the `format_tt()` function instead. #' @param caption A string that will be used as the caption of the table. This argument should *not* be used in Quarto or Rmarkdown documents. In that context, please use the appropriate chunk options. -#' @param width Table or column width. -#' - Single numeric value smaller than or equal to 1 determines the full table width, in proportion of line width. +#' @param width Table or column width. +#' - Single numeric value smaller than or equal to 1 determines the full table width, in proportion of line width. #' - Numeric vector of length equal to the number of columns in `x` determines the width of each column, in proportion of line width. If the sum of `width` exceeds 1, each element is divided by `sum(width)`. This makes the table full-width with relative column sizes. #' @param theme Function or string. #' - String: `r paste(setdiff(names(theme_dictionary), "default"), collapse = ", ")` @@ -30,32 +30,33 @@ #' @param escape Logical. If `TRUE`, escape special characters in the table. Equivalent to `format_tt(tt(x), escape = TRUE)`. #' @param ... Additional arguments are ignored #' @return An object of class `tt` representing the table. -#' +#' #' The table object has S4 slots which hold information about the structure of the table. Relying on or modifying the contents of these slots is strongly discouraged. Their names and contents could change at any time, and the `tinytable` developers do not consider changes to the internal structure of the output object to be a "breaking change" for versioning or changelog purposes. #' @template dependencies #' @template latex_preamble +#' @template limitations_word_markdown #' @template global_options -#' +#' #' @examples #' library(tinytable) #' x <- mtcars[1:4, 1:5] #' #' tt(x) -#' +#' #' tt(x, -#' theme = "striped", -#' width = 0.5, -#' caption = "Data about cars.") -#' +#' theme = "striped", +#' width = 0.5, +#' caption = "Data about cars.") +#' #' tt(x, notes = "Hello World!") #' #' fn <- list(i = 0:1, j = 2, text = "Hello World!") #' tab <- tt(x, notes = list("*" = fn)) #' print(tab, "latex") -#' +#' #' k <- data.frame(x = c(0.000123456789, 12.4356789)) -#' tt(k, digits=2) -#' +#' tt(k, digits = 2) +#' #' @export tt <- function(x, digits = get_option("tinytable_tt_digits", default = NULL), @@ -66,8 +67,6 @@ tt <- function(x, rownames = get_option("tinytable_tt_rownames", default = FALSE), escape = get_option("tinytable_tt_escape", default = FALSE), ...) { - - dots <- list(...) # sanity checks @@ -91,20 +90,20 @@ tt <- function(x, # it might be dangerous to leave non-numerics, but what about dates and other character-coercibles? for (i in seq_along(x)) { if (is.factor(x[[i]])) { - x[[i]] <- as.character(x[[i]]) + x[[i]] <- as.character(x[[i]]) } } assert_numeric(width, lower = 0, null.ok = TRUE) if (!length(width) %in% c(0, 1, ncol(x))) { - msg <- sprintf("The `width` argument must have length 1 or %s.", ncol(x)) - stop(msg, call. = FALSE) + msg <- sprintf("The `width` argument must have length 1 or %s.", ncol(x)) + stop(msg, call. = FALSE) } if (sum(width) > 1) { - width <- width / sum(width) + width <- width / sum(width) } - # bind the row names if the user explicitly asks for it in global option. + # bind the row names if the user explicitly asks for it in global option. # Same name as tibble::rownames_to_column() assert_flag(rownames) if (isTRUE(rownames) && !is.null(row.names(x))) { diff --git a/man-roxygen/limitations_word_markdown.R b/man-roxygen/limitations_word_markdown.R new file mode 100644 index 00000000..4c668ad5 --- /dev/null +++ b/man-roxygen/limitations_word_markdown.R @@ -0,0 +1,8 @@ +#' @section Word and Markdown limitations: +#' +#' Markdown and Word tables only support these styles: italic, bold, strikeout. The `width` arugment is also unavailable +#' Moreover, the `style_tt()` function cannot be used to style headers inserted by the `group_tt()` function; +#' instead, you should style the headers directly in the header definition using markdown syntax: +#' `group_tt(i = list("*italic header*" = 2))`. These limitations are due to the fact that there is no markdown +#' syntax for the other options, and that we create Word documents by converting a markdown table to .docx +#' via the Pandoc software. diff --git a/man/group_tt.Rd b/man/group_tt.Rd index e7fd6d23..082335b6 100644 --- a/man/group_tt.Rd +++ b/man/group_tt.Rd @@ -31,13 +31,24 @@ Spanning labels to identify groups of rows or columns \details{ Warning: The \code{style_tt()} can normally be used to style the group headers, as expected, but that feature is not available for Markdown and Word tables. } +\section{Word and Markdown limitations}{ + + +Markdown and Word tables only support these styles: italic, bold, strikeout. The \code{width} arugment is also unavailable +Moreover, the \code{style_tt()} function cannot be used to style headers inserted by the \code{group_tt()} function; +instead, you should style the headers directly in the header definition using markdown syntax: +\code{group_tt(i = list("*italic header*" = 2))}. These limitations are due to the fact that there is no markdown +syntax for the other options, and that we create Word documents by converting a markdown table to .docx +via the Pandoc software. +} + \examples{ # vector of row labels dat <- data.frame( - label = c("a", "a", "a", "b", "b", "c", "a", "a"), - x1 = rnorm(8), - x2 = rnorm(8)) + label = c("a", "a", "a", "b", "b", "c", "a", "a"), + x1 = rnorm(8), + x2 = rnorm(8)) tt(dat[, 2:3]) |> group_tt(i = dat$label) # named lists of labels diff --git a/man/style_tt.Rd b/man/style_tt.Rd index f6c48004..bdd077fe 100644 --- a/man/style_tt.Rd +++ b/man/style_tt.Rd @@ -123,9 +123,18 @@ Style a Tiny Table } \details{ This function applies styling to a table created by \code{tt()}. It allows customization of text style (bold, italic, monospace), text and background colors, font size, cell width, text alignment, column span, and indentation. The function also supports passing native instructions to LaTeX (tabularray) and HTML (bootstrap) formats. +} +\section{Word and Markdown limitations}{ + -Note: Markdown and Word tables only support these styles: italic, bold, strikeout. Moreover, the \code{style_tt()} function cannot be used to style headers inserted by the \code{group_tt()} function; instead, you should style the headers directly in the header definition using markdown syntax: \code{group_tt(i = list("*italic header*" = 2))}. These limitations are due to the fact that there is no markdown syntax for the other options, and that we create Word documents by converting a markdown table to .docx via the Pandoc software. +Markdown and Word tables only support these styles: italic, bold, strikeout. The \code{width} arugment is also unavailable +Moreover, the \code{style_tt()} function cannot be used to style headers inserted by the \code{group_tt()} function; +instead, you should style the headers directly in the header definition using markdown syntax: +\code{group_tt(i = list("*italic header*" = 2))}. These limitations are due to the fact that there is no markdown +syntax for the other options, and that we create Word documents by converting a markdown table to .docx +via the Pandoc software. } + \examples{ \dontshow{if (knitr::is_html_output()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \dontshow{\}) # examplesIf} @@ -136,15 +145,15 @@ library(tinytable) tt(mtcars[1:5, 1:6]) # Alignment -tt(mtcars[1:5, 1:6]) |> +tt(mtcars[1:5, 1:6]) |> style_tt(j = 1:5, align = "lcccr") # Colors and styles -tt(mtcars[1:5, 1:6]) |> +tt(mtcars[1:5, 1:6]) |> style_tt(i = 2:3, background = "black", color = "orange", bold = TRUE) # column selection with `j`` -tt(mtcars[1:5, 1:6]) |> +tt(mtcars[1:5, 1:6]) |> style_tt(j = 5:6, background = "pink") tt(mtcars[1:5, 1:6]) |> @@ -158,27 +167,27 @@ tt(mtcars[1:5, 1:6], theme = "void") |> i = 2, j = 2, colspan = 3, rowspan = 2, - align="c", + align = "c", alignv = "m", color = "white", background = "black", bold = TRUE) - + tt(mtcars[1:5, 1:6], theme = "void") |> style_tt( - i=0:3, - j=1:3, - line="tblr", - line_width=0.4, - line_color="teal") - + i = 0:3, + j = 1:3, + line = "tblr", + line_width = 0.4, + line_color = "teal") + tt(mtcars[1:5, 1:6], theme = "bootstrap") |> - style_tt( - i = c(2,5), - j = 3, - strikeout = TRUE, - fontsize = 0.7) - + style_tt( + i = c(2, 5), + j = 3, + strikeout = TRUE, + fontsize = 0.7) + tt(mtcars[1:5, 1:6]) |> style_tt(bootstrap_class = "table table-dark table-hover") diff --git a/man/tt.Rd b/man/tt.Rd index ad8638ef..ae6bcae3 100644 --- a/man/tt.Rd +++ b/man/tt.Rd @@ -98,6 +98,17 @@ Note: Your document will fail to compile to PDF in Quarto if you enable caching }\if{html}{\out{}} } +\section{Word and Markdown limitations}{ + + +Markdown and Word tables only support these styles: italic, bold, strikeout. The \code{width} arugment is also unavailable +Moreover, the \code{style_tt()} function cannot be used to style headers inserted by the \code{group_tt()} function; +instead, you should style the headers directly in the header definition using markdown syntax: +\code{group_tt(i = list("*italic header*" = 2))}. These limitations are due to the fact that there is no markdown +syntax for the other options, and that we create Word documents by converting a markdown table to .docx +via the Pandoc software. +} + \section{Global options}{ @@ -169,9 +180,9 @@ x <- mtcars[1:4, 1:5] tt(x) tt(x, - theme = "striped", - width = 0.5, - caption = "Data about cars.") + theme = "striped", + width = 0.5, + caption = "Data about cars.") tt(x, notes = "Hello World!") @@ -180,6 +191,6 @@ tab <- tt(x, notes = list("*" = fn)) print(tab, "latex") k <- data.frame(x = c(0.000123456789, 12.4356789)) -tt(k, digits=2) +tt(k, digits = 2) }