diff --git a/NEWS.md b/NEWS.md index 3bb407aab..c56c1d867 100644 --- a/NEWS.md +++ b/NEWS.md @@ -21,6 +21,7 @@ * Fixed bug in `as_html` preventing indentation from being applied in `Viewer` output. * `col_counts<-` and `col_total<-` methods now explicitly convert `value` to integer, by @gmbecker. * `col_gap` is now respected in `nlines` row methods, and thus by `make_row_df`, by @gmbecker. + * Updated `as_html` to accommodate `\n` characters. ### Miscellaneous diff --git a/R/as_html.R b/R/as_html.R index ffb9705d2..889c06d5c 100644 --- a/R/as_html.R +++ b/R/as_html.R @@ -80,15 +80,16 @@ as_html <- function(x, nlh <- mf_nlheader(mat) nc <- ncol(x) + 1 + nr <- length(mf_lgrouping(mat)) # Structure is a list of lists with rows (one for each line grouping) and cols as dimensions - cells <- matrix(rep(list(list()), (nlh + nrow(x)) * (nc)), ncol = nc) + cells <- matrix(rep(list(list()), (nr * nc)), ncol = nc) - for (i in seq_len(nrow(mat$strings))) { - for (j in seq_len(ncol(mat$strings))) { - curstrs <- mat$strings[i, j] - curspn <- mat$spans[i, j] - algn <- mat$aligns[i, j] + for (i in seq_len(nr)) { + for (j in seq_len(nc)) { + curstrs <- mf_strings(mat)[i, j] + curspn <- mf_spans(mat)[i, j] + algn <- mf_aligns(mat)[i, j] inhdr <- i <= nlh tagfun <- if (inhdr) tags$th else tags$td @@ -110,18 +111,32 @@ as_html <- function(x, ) } - # row labels style - for (i in seq_len(nrow(x))) { - indent <- mat$row_info$indent[i] - if (indent > 0) { # indentation - cells[i + nlh, 1][[1]] <- htmltools::tagAppendAttributes(cells[i + nlh, 1][[1]], + # Create a map between line numbers and line groupings, adjusting abs_rownumber with nlh + map <- data.frame(lines = seq_len(nr), abs_rownumber = mat$line_grouping) + row_info_df <- data.frame(indent = mat$row_info$indent, abs_rownumber = mat$row_info$abs_rownumber + nlh) + map <- merge(map, row_info_df, by = "abs_rownumber") + + # add indent values for headerlines + map <- rbind(data.frame(abs_rownumber = 1:nlh, indent = 0, lines = 0), map) + + + # Row labels style + for (i in seq_len(nr)) { + indent <- ifelse(any(map$lines == i), map$indent[map$lines == i][1], -1) + + # Apply indentation + if (indent > 0) { + cells[i, 1][[1]] <- htmltools::tagAppendAttributes( + cells[i, 1][[1]], style = paste0("padding-left: ", indent * 3, "ch;") ) } - if ("row_names" %in% bold) { # font weight - cells[i + nlh, 1][[1]] <- htmltools::tagAppendAttributes( - cells[i + nlh, 1][[1]], - style = paste0("font-weight: bold;") + + # Apply bold font weight if "row_names" is in 'bold' + if ("row_names" %in% bold) { + cells[i, 1][[1]] <- htmltools::tagAppendAttributes( + cells[i, 1][[1]], + style = "font-weight: bold;" ) } } diff --git a/R/make_split_fun.R b/R/make_split_fun.R index aff197de1..acceb40e0 100644 --- a/R/make_split_fun.R +++ b/R/make_split_fun.R @@ -348,7 +348,7 @@ add_combo_facet <- function(name, label = name, levels, extra = list()) { subexpr <- expression(TRUE) datpart <- list(fulldf) } else { - subexpr <- .combine_value_exprs(ret$value[levels]) + subexpr <- .combine_value_exprs(ret$values[levels]) datpart <- list(do.call(rbind, ret$datasplit[levels])) } diff --git a/inst/WORDLIST b/inst/WORDLIST index d929f7c6f..af9b133ca 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -46,6 +46,7 @@ flextable formatter formatters funder +funs getter getters ing @@ -57,12 +58,14 @@ mandatorily monospace multivariable orderable +params pathing postfix postprocessing pre priori programmatically +quartiles reindexed repo repped diff --git a/tests/testthat/test-exporters.R b/tests/testthat/test-exporters.R index c11103921..b5bcc7941 100644 --- a/tests/testthat/test-exporters.R +++ b/tests/testthat/test-exporters.R @@ -293,6 +293,36 @@ test_that("as_html header line works", { expect_true(all(sapply(1:4, function(x) "border-bottom: 1px solid black;" %in% html_parts[[x]]$attribs))) }) +# https://github.com/insightsengineering/rtables/issues/872 +test_that("as_html indentation is translated to rows with linebreaks", { + lyt <- basic_table() %>% + split_cols_by("ARM") %>% + split_rows_by("SEX") %>% + analyze("AGE", afun = function(x) { + mn <- round(mean(x), 2) + if (!is.nan(mn) && mn > mean(DM$AGE)) { + val <- paste(mn, " ^ ", sep = "\n") + } else { + val <- paste(mn) + } + in_rows(my_row_label = rcell(val, + format = "xx" + )) + }) + tbl <- build_table(lyt, DM) + + # Resolves correctly \n + expect_silent(res <- as_html(tbl)) + expect_equal( + as.character(res$children[[1]][[2]]$children[[7]]$children[[1]][[1]]), + '