Skip to content

Commit

Permalink
close #2024: add a new output format 'jira' to kable() (#2180)
Browse files Browse the repository at this point in the history
Co-authored-by: Yihui Xie <xie@yihui.name>
  • Loading branch information
pedropark99 and yihui committed Oct 6, 2022
1 parent ff3d767 commit b3936ca
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 6 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Authors@R: c(
person("Noam", "Ross", role = "ctb"),
person("Obada", "Mahdi", role = "ctb"),
person("Pavel N.", "Krivitsky", role = "ctb", comment=c(ORCID = "0000-0002-9101-3362")),
person("Pedro", "Faria", role = "ctb"),
person("Qiang", "Li", role = "ctb"),
person("Ramnath", "Vaidyanathan", role = "ctb"),
person("Richard", "Cotton", role = "ctb"),
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGES IN knitr VERSION 1.41

## NEW FEATURES

- Added support for generating Jira tables via `kable(, format = 'jira')` (thanks, @pedropark99 #2180, @mruessler #2024).

## BUG FIXES

- Plot created outside of `knit()` could sneak into `knit_child()` results (thanks, @niklaswillrich, #2166).
Expand Down
35 changes: 30 additions & 5 deletions R/table.R
Original file line number Diff line number Diff line change
Expand Up @@ -377,16 +377,20 @@ kable_html = function(
#'
#' This function provides the basis for Markdown and reST tables.
#' @param x The data matrix.
#' @param sep.row A length-3 character vector, specifying separators to be printed
#' before the header, after the header, and at the end of the table respectively.
#' @param sep.row A length-3 character vector, specifying separators to be
#' printed before the header, after the header, and at the end of the table
#' respectively.
#' @param sep.col The column separator.
#' @param sep.head The column separator for the header of the table (i.e., the
#' line with the column names).
#' @param padding Number of spaces for the table cell padding.
#' @param align.fun A function to process the separator under the header
#' according to the alignment.
#' @return A character vector of the table content.
#' @noRd
kable_mark = function(x, sep.row = c('=', '=', '='), sep.col = ' ', padding = 0,
align.fun = function(s, a) s, rownames.name = '', ...) {
align.fun = function(s, a) s, rownames.name = '',
sep.head = sep.col, ...) {
# when the column separator is |, replace existing | with its HTML entity
if (sep.col == '|') for (j in seq_len(ncol(x))) {
x[, j] = gsub('\\|', '&#124;', x[, j])
Expand All @@ -395,7 +399,7 @@ kable_mark = function(x, sep.row = c('=', '=', '='), sep.col = ' ', padding = 0
cn = colnames(x)
if (length(cn) > 0) {
cn[is.na(cn)] = "NA"
if (sep.col == '|') cn = gsub('\\|', '&#124;', cn)
if (sep.head == '|') cn = gsub('\\|', '&#124;', cn)
if (grepl('^\\s*$', cn[1L])) cn[1L] = rownames.name # no empty cells for reST
l = pmax(if (length(l) == 0) 0 else l, nchar(remove_urls(cn), type = 'width'))
}
Expand All @@ -407,7 +411,17 @@ kable_mark = function(x, sep.row = c('=', '=', '='), sep.col = ' ', padding = 0
s = unlist(lapply(l, function(i) paste(rep(sep.row[2], i), collapse = '')))
res = rbind(if (!is.na(sep.row[1])) s, cn, align.fun(s, align),
x, if (!is.na(sep.row[3])) s)
apply(mat_pad(res, l, align), 1, paste, collapse = sep.col)
res = mat_pad(res, l, align)
add_mark_col_sep(res, sep.col, sep.head)
}

# add column separators to header and body separately
add_mark_col_sep = function(table, sep.col, sep.head) {
if (any(dim(table) == 0)) return(table)
h = paste(table[1, ], collapse = sep.head) # header
b = table[-1, , drop = FALSE]
b = apply(b, 1, paste, collapse = sep.col) # body
c(h, b)
}

kable_rst = function(x, rownames.name = '\\', ...) {
Expand Down Expand Up @@ -441,6 +455,17 @@ kable_simple = function(x, caption = NULL, padding = 1, ...) {
kable_pandoc_caption(tab, caption)
}

# Jira table
kable_jira = function(x, caption = NULL, padding = 1, ...) {
tab = kable_mark(x, c(NA, NA, NA), '|', padding, sep.head = '||', ...)
if ((n <- length(tab)) == 0) return(tab)
# remove the line that separates the table header from the table body
if (n >= 2) tab = tab[-2]
tab[1] = sprintf('||%s||', tab[1])
tab[-1] = sprintf('|%s|', tab[-1])
kable_pandoc_caption(tab, caption)
}

kable_pandoc_caption = function(x, caption) {
if (identical(caption, NA)) caption = NULL
if (length(caption)) c(paste('Table:', caption), "", x) else x
Expand Down
6 changes: 5 additions & 1 deletion tests/testit/test-table.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ assert("kable() works on NA's", {
c('|x |', '|:-----|', '|NA |', '|FALSE |'))
})

assert('kable() works with the jira format', {
(kable2(m, 'jira') %==% c('|| || x|| y||', '|a | 1| 2|'))
})

assert('kable() does not add extra spaces to character columns', {
(kable2(data.frame(x = c(1.2, 4.87), y = c('fooooo', 'bar')), 'latex') %==% '
\\begin{tabular}{r|l}
Expand Down Expand Up @@ -127,7 +131,7 @@ assert('kable() works on matrices with NA colname', {
x1 = matrix(NA, 0, 0)
x2 = matrix(NA, 0, 1)
x3 = matrix(NA, 1, 0)
for (f in c('simple', 'html', 'latex', 'rst')) {
for (f in c('simple', 'html', 'latex', 'rst', 'jira')) {
kable(x1, f)
kable(x2, f)
kable(x3, f)
Expand Down

0 comments on commit b3936ca

Please sign in to comment.