blob: bddc5e4b53ae2f7cf7d04bede923c40e6e002ec4 [file] [log] [blame]
Hao Zhu8f417202017-05-20 16:37:14 -04001#' Add indentations to row headers
Hao Zhubd95bb22017-05-22 16:08:49 -04002#'
3#' @param kable_input Output of `knitr::kable()` with `format` specified
4#' @param positions A vector of numeric row numbers for the rows that need to
5#' be indented.
Samia67d70572020-07-06 00:54:13 -04006#' @param level_of_indent a numeric value for the indent level
Hao Zhubd95bb22017-05-22 16:08:49 -04007#'
Hao Zhu78e61222017-05-24 20:53:35 -04008#' @examples x <- knitr::kable(head(mtcars), "html")
9#' # Add indentations to the 2nd & 4th row
Samia67d70572020-07-06 00:54:13 -040010#' add_indent(x, c(2, 4), level_of_indent = 1)
Hao Zhu78e61222017-05-24 20:53:35 -040011#'
Hao Zhu8f417202017-05-20 16:37:14 -040012#' @export
Samia67d70572020-07-06 00:54:13 -040013add_indent <- function(kable_input, positions, level_of_indent) {
Samia106ad582020-07-15 14:19:09 -040014
15 if(missing(level_of_indent)){
16 level_of_indent = 1
17 }else{
18 level_of_indent = level_of_indent
19 }
20
Hao Zhud972e7f2017-05-22 13:27:15 -040021 if (!is.numeric(positions)) {
22 stop("Positions can only take numeric row numbers (excluding header rows).")
23 }
Hao Zhu8f417202017-05-20 16:37:14 -040024 kable_format <- attr(kable_input, "format")
25 if (!kable_format %in% c("html", "latex")) {
Hao Zhu401ebd82018-01-14 17:10:20 -050026 warning("Please specify format in kable. kableExtra can customize either ",
27 "HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ ",
28 "for details.")
Hao Zhu8f417202017-05-20 16:37:14 -040029 return(kable_input)
30 }
31 if (kable_format == "html") {
Samia67d70572020-07-06 00:54:13 -040032 return(add_indent_html(kable_input, positions, level_of_indent))
Hao Zhu8f417202017-05-20 16:37:14 -040033 }
34 if (kable_format == "latex") {
Samia67d70572020-07-06 00:54:13 -040035 return(add_indent_latex(kable_input, positions, level_of_indent))
Hao Zhu8f417202017-05-20 16:37:14 -040036 }
37}
38
Hao Zhu62cdde52017-05-20 22:16:03 -040039# Add indentation for LaTeX
Samia67d70572020-07-06 00:54:13 -040040add_indent_latex <- function(kable_input, positions, level_of_indent) {
Hao Zhud972e7f2017-05-22 13:27:15 -040041 table_info <- magic_mirror(kable_input)
Hao Zhu3fc0e882018-04-03 16:06:41 -040042 out <- solve_enc(kable_input)
Samia67d70572020-07-06 00:54:13 -040043 level_of_indent<-as.numeric(level_of_indent)
Samia6c4b24f2020-07-06 00:46:41 -040044
Samia106ad582020-07-15 14:19:09 -040045 if(missing(level_of_indent)){
46 level_of_indent = 1
47 }else{
48 level_of_indent = level_of_indent
49 }
Hao Zhu064990d2017-10-17 18:08:42 -040050
51 if (table_info$duplicated_rows) {
52 dup_fx_out <- fix_duplicated_rows_latex(out, table_info)
53 out <- dup_fx_out[[1]]
54 table_info <- dup_fx_out[[2]]
55 }
Hao Zhu8f417202017-05-20 16:37:14 -040056
Hao Zhu37dbe3f2018-05-14 11:16:06 -040057 max_position <- table_info$nrow - table_info$position_offset
Leo83f05132018-05-10 14:12:16 +080058
59 if (max(positions) > max_position) {
Hao Zhu8f417202017-05-20 16:37:14 -040060 stop("There aren't that many rows in the table. Check positions in ",
61 "add_indent_latex.")
62 }
63
Hao Zhu37dbe3f2018-05-14 11:16:06 -040064 for (i in positions + table_info$position_offset) {
Leo83f05132018-05-10 14:12:16 +080065 rowtext <- table_info$contents[i]
Hao Zhu09d01262019-01-07 22:06:22 -050066 out <- sub(paste0(rowtext, "\\\\\\\\"),
67 paste0(latex_indent_unit(rowtext), "\\\\\\\\"),
Quôc Peyroted7e6242018-09-05 14:59:16 +020068 out, perl = TRUE)
Leo83f05132018-05-10 14:12:16 +080069 table_info$contents[i] <- latex_indent_unit(rowtext)
Hao Zhu8f417202017-05-20 16:37:14 -040070 }
Hao Zhu2ce42b92017-06-15 17:15:33 -040071 out <- structure(out, format = "latex", class = "knitr_kable")
Hao Zhu32f43f72017-06-20 18:24:54 -040072 attr(out, "kable_meta") <- table_info
Hao Zhu8f417202017-05-20 16:37:14 -040073 return(out)
Samia6c4b24f2020-07-06 00:46:41 -040074
75
Hao Zhu8f417202017-05-20 16:37:14 -040076}
77
78latex_indent_unit <- function(rowtext) {
Samia67d70572020-07-06 00:54:13 -040079 paste0("\\\\hspace\\{",level_of_indent,"em\\}", rowtext)
Hao Zhu8f417202017-05-20 16:37:14 -040080}
Hao Zhu62cdde52017-05-20 22:16:03 -040081
Samia6c4b24f2020-07-06 00:46:41 -040082
83
Hao Zhu62cdde52017-05-20 22:16:03 -040084# Add indentation for HTML
Samia67d70572020-07-06 00:54:13 -040085add_indent_html <- function(kable_input, positions, level_of_indent) {
Samia106ad582020-07-15 14:19:09 -040086
87 if(missing(level_of_indent)){
88 level_of_indent = 1
89 }else{
90 level_of_indent = level_of_indent
91 }
92
Hao Zhu62cdde52017-05-20 22:16:03 -040093 kable_attrs <- attributes(kable_input)
94
Hao Zhu558c72f2017-07-24 15:12:00 -040095 kable_xml <- read_kable_as_xml(kable_input)
Hao Zhu62cdde52017-05-20 22:16:03 -040096 kable_tbody <- xml_tpart(kable_xml, "tbody")
97
98 group_header_rows <- attr(kable_input, "group_header_rows")
99 if (!is.null(group_header_rows)) {
100 positions <- positions_corrector(positions, group_header_rows,
101 length(xml_children(kable_tbody)))
102 }
Alan Butlerc81c1fe2018-01-30 11:16:18 -0700103
Hao Zhu62cdde52017-05-20 22:16:03 -0400104 for (i in positions) {
105 node_to_edit <- xml_child(xml_children(kable_tbody)[[i]], 1)
Alan Butlerc81c1fe2018-01-30 11:16:18 -0700106 if (!xml_has_attr(node_to_edit, "indentlevel")) {
Hao Zhu62cdde52017-05-20 22:16:03 -0400107 xml_attr(node_to_edit, "style") <- paste(
Samia67d70572020-07-06 00:54:13 -0400108 xml_attr(node_to_edit, "style"), "padding-left: ",paste0(level_of_indent*2,"em;")
Hao Zhu62cdde52017-05-20 22:16:03 -0400109 )
Alan Butlerc81c1fe2018-01-30 11:16:18 -0700110 xml_attr(node_to_edit, "indentlevel") <- 1
Hao Zhu62cdde52017-05-20 22:16:03 -0400111 } else {
Alan Butlerc81c1fe2018-01-30 11:16:18 -0700112 indentLevel <- as.numeric(xml_attr(node_to_edit, "indentlevel"))
Hao Zhu62cdde52017-05-20 22:16:03 -0400113 xml_attr(node_to_edit, "style") <- sub(
114 paste0("padding-left: ", indentLevel * 2, "em;"),
115 paste0("padding-left: ", (indentLevel + 1) * 2, "em;"),
116 xml_attr(node_to_edit, "style")
117 )
Alan Butlerc81c1fe2018-01-30 11:16:18 -0700118 xml_attr(node_to_edit, "indentlevel") <- indentLevel + 1
Hao Zhu62cdde52017-05-20 22:16:03 -0400119 }
120 }
Hao Zhuf2dfd142017-07-24 14:43:28 -0400121 out <- as_kable_xml(kable_xml)
Hao Zhu62cdde52017-05-20 22:16:03 -0400122 attributes(out) <- kable_attrs
Hao Zhuf2100832018-01-11 16:20:29 -0500123 if (!"kableExtra" %in% class(out)) class(out) <- c("kableExtra", class(out))
Hao Zhu62cdde52017-05-20 22:16:03 -0400124 return(out)
125}