Skip to content

Commit

Permalink
Fix issue rstudio#1465
Browse files Browse the repository at this point in the history
Replaces the use of percentage symbols to express column widths, which cause an error when compiling Latex, with column widths that are expressed as a share of `\linewidth` or the user-supplied `table_width`.
  • Loading branch information
kbrevoort committed Nov 11, 2023
1 parent a345f85 commit edc4059
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 0 deletions.
39 changes: 39 additions & 0 deletions R/utils_render_latex.R
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,45 @@ create_table_start_l <- function(data) {
">{\\raggedright\\arraybackslash}"
)

# Check if column width was set using gt::pct and
# convert to Latex friendly terminology (i.e.,
# '14.7%' becomes '0.147\\linewidth')
if (grepl('^[[:digit:].]+%$', col_widths[i])) {

table_width <- dt_options_get_value(data = data, option = 'table_width')

col_pct <- as.numeric(gsub('%$', '', col_widths[i])) / 100

if (table_width == 'auto') {

# Table width not specified, use all available space
col_scalar <- col_pct
tab_unit <- '\\linewidth'

} else if (endsWith(table_width, suffix = '%')) {

# If table width is expressed as a percentage, adjust the scaler
col_scalar <- col_pct * as.numeric(gsub('%', '', table_width)) / 100
tab_unit <- '\\linewidth'

} else {

# When table width is expressed in units, convert to points
col_scalar <- col_pct * convert_to_px(table_width) * 0.75 # 0.75 converts pixels to points
tab_unit <- 'pt'

}

col_widths[i] <-
paste0(
"\\dimexpr ",
col_scalar,
tab_unit,
"-2\\tabcolsep-1.5\\arrayrulewidth"
)

}

col_defs_i <- paste0(align, "p{", col_widths[i], "}")

} else {
Expand Down
108 changes: 108 additions & 0 deletions tests/testthat/test-cols_width.R
Original file line number Diff line number Diff line change
Expand Up @@ -897,3 +897,111 @@ test_that("The function `cols_width()` works correctly with a complex table", {
) %>%
expect_true()
})

test_that("The function `cols_width()` correctly specifies LaTeX table when column widths are specified by user as percentages", {

# Check that specific suggested packages are available
check_suggests()

# Create a `tbl_latex` object with `gt()` and size
# all columns in percentages
tbl_latex <-
gt(tbl) %>%
cols_width(
col_1 ~ pct(50),
col_2 ~ pct(30),
col_3 ~ pct(20),
col_4 ~ pct(10)
)

pct_string <- function(x, unit = '\\\\linewidth') {

prefix <- '>\\{\\\\ragged[[:alpha:]]+\\\\arraybackslash\\}'

sprintf(
'%sp\\{\\\\dimexpr %s%s-2\\\\tabcolsep-1.5\\\\arrayrulewidth\\}',
prefix,
format(x, scientific = FALSE, trim = TRUE),
unit
)

}

build_longtable_regex <- function(...) {

paste0(
c(
"^\\\\begin\\{longtable\\}\\{",
c(...),
"\\}\\n"
),
collapse = ''
)

}

latex_col_regex <-
paste0(
c(
'^\\\\begin\\{longtable\\}\\{',
# '>\\{\\\\ragged[[:alpha:]]+\\\\arraybackslash'
sprintf('>\\{\\\\ragged[[:alpha:]]+\\\\arraybackslash\\}p\\{\\\\dimexpr 0\\.%d\\\\linewidth-2\\\\tabcolsep-1.5\\\\arrayrulewidth}',
c(5L, 3L, 2L, 1L)),
'\\}\\n'
),
collapse = ''
)

# Expect that all column widths are expressed as percentage of \linewidth
c(0.5, 0.3, 0.2, 0.1) %>%
pct_string() %>%
build_longtable_regex() %>%
grepl(as_latex(tbl_latex)) %>%
expect_true()


# Check that LaTeX is correctly generated when only some
# column widths are specified as percentages
tbl_latex_partial <-
gt(tbl) %>%
cols_width(
col_1 ~ pct(30),
col_3 ~ pct(20)
)

c(
pct_string(0.3),
'r',
pct_string(0.2),
'r'
) %>%
build_longtable_regex() %>%
grepl(as_latex(tbl_latex_partial)) %>%
expect_true()

# Check that LaTeX longtable command is correctly generated
# when table_width is specified by the user as a percentage
tbl_latex_tw_pct <-
tbl_latex %>%
tab_options(table.width = pct(70))

(0.7 * c(0.5, 0.3, 0.2, 0.1)) %>%
pct_string() %>%
build_longtable_regex() %>%
grepl(as_latex(tbl_latex_tw_pct)) %>%
expect_true()

# Check that LaTeX longtable command is correctly generated
# when table width is specified by user in pixels
tbl_latex_tw_px <-
tbl_latex %>%
tab_options(table.width = '400px')

(400 * 0.75 * c(0.5, 0.3, 0.2, 0.1)) %>%
pct_string(unit = 'pt') %>%
build_longtable_regex() %>%
grepl(as_latex(tbl_latex_tw_px))


})

0 comments on commit edc4059

Please sign in to comment.