blob: c0e1c1e74b4cd996b69728ddb79029740142e657 [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.
6#'
Hao Zhu78e61222017-05-24 20:53:35 -04007#' @examples x <- knitr::kable(head(mtcars), "html")
8#' # Add indentations to the 2nd & 4th row
9#' add_indent(x, c(2, 4))
10#'
Hao Zhu8f417202017-05-20 16:37:14 -040011#' @export
12add_indent <- function(kable_input, positions) {
Hao Zhud972e7f2017-05-22 13:27:15 -040013 if (!is.numeric(positions)) {
14 stop("Positions can only take numeric row numbers (excluding header rows).")
15 }
Hao Zhu8f417202017-05-20 16:37:14 -040016 kable_format <- attr(kable_input, "format")
17 if (!kable_format %in% c("html", "latex")) {
Hao Zhu401ebd82018-01-14 17:10:20 -050018 warning("Please specify format in kable. kableExtra can customize either ",
19 "HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ ",
20 "for details.")
Hao Zhu8f417202017-05-20 16:37:14 -040021 return(kable_input)
22 }
23 if (kable_format == "html") {
Hao Zhu62cdde52017-05-20 22:16:03 -040024 return(add_indent_html(kable_input, positions))
Hao Zhu8f417202017-05-20 16:37:14 -040025 }
26 if (kable_format == "latex") {
27 return(add_indent_latex(kable_input, positions))
28 }
29}
30
Hao Zhu62cdde52017-05-20 22:16:03 -040031# Add indentation for LaTeX
Hao Zhu8f417202017-05-20 16:37:14 -040032add_indent_latex <- function(kable_input, positions) {
Hao Zhud972e7f2017-05-22 13:27:15 -040033 table_info <- magic_mirror(kable_input)
Hao Zhu3fc0e882018-04-03 16:06:41 -040034 out <- solve_enc(kable_input)
Hao Zhu064990d2017-10-17 18:08:42 -040035
36 if (table_info$duplicated_rows) {
37 dup_fx_out <- fix_duplicated_rows_latex(out, table_info)
38 out <- dup_fx_out[[1]]
39 table_info <- dup_fx_out[[2]]
40 }
Hao Zhu8f417202017-05-20 16:37:14 -040041
Leo83f05132018-05-10 14:12:16 +080042 if (table_info$booktabs & is.null(table_info$colnames)) {
43 max_position <- table_info$nrow
44 position_offset <- 0
45 } else {
46 max_position <- table_info$nrow - 1
47 position_offset <- 1
48 }
49
50 if (max(positions) > max_position) {
Hao Zhu8f417202017-05-20 16:37:14 -040051 stop("There aren't that many rows in the table. Check positions in ",
52 "add_indent_latex.")
53 }
54
Leo83f05132018-05-10 14:12:16 +080055 for (i in positions + position_offset) {
56 rowtext <- table_info$contents[i]
Hao Zhue5bfbf12017-06-06 00:24:49 -040057 out <- sub(rowtext, latex_indent_unit(rowtext), out, perl = TRUE)
Leo83f05132018-05-10 14:12:16 +080058 table_info$contents[i] <- latex_indent_unit(rowtext)
Hao Zhu8f417202017-05-20 16:37:14 -040059 }
Hao Zhu2ce42b92017-06-15 17:15:33 -040060 out <- structure(out, format = "latex", class = "knitr_kable")
Hao Zhu32f43f72017-06-20 18:24:54 -040061 attr(out, "kable_meta") <- table_info
Hao Zhu8f417202017-05-20 16:37:14 -040062 return(out)
63}
64
65latex_indent_unit <- function(rowtext) {
Hao Zhu2ce42b92017-06-15 17:15:33 -040066 paste0("\\\\hspace\\{1em\\}", rowtext)
Hao Zhu8f417202017-05-20 16:37:14 -040067}
Hao Zhu62cdde52017-05-20 22:16:03 -040068
69# Add indentation for HTML
70add_indent_html <- function(kable_input, positions) {
71 kable_attrs <- attributes(kable_input)
72
Hao Zhu558c72f2017-07-24 15:12:00 -040073 kable_xml <- read_kable_as_xml(kable_input)
Hao Zhu62cdde52017-05-20 22:16:03 -040074 kable_tbody <- xml_tpart(kable_xml, "tbody")
75
76 group_header_rows <- attr(kable_input, "group_header_rows")
77 if (!is.null(group_header_rows)) {
78 positions <- positions_corrector(positions, group_header_rows,
79 length(xml_children(kable_tbody)))
80 }
Alan Butlerc81c1fe2018-01-30 11:16:18 -070081
Hao Zhu62cdde52017-05-20 22:16:03 -040082 for (i in positions) {
83 node_to_edit <- xml_child(xml_children(kable_tbody)[[i]], 1)
Alan Butlerc81c1fe2018-01-30 11:16:18 -070084 if (!xml_has_attr(node_to_edit, "indentlevel")) {
Hao Zhu62cdde52017-05-20 22:16:03 -040085 xml_attr(node_to_edit, "style") <- paste(
86 xml_attr(node_to_edit, "style"), "padding-left: 2em;"
87 )
Alan Butlerc81c1fe2018-01-30 11:16:18 -070088 xml_attr(node_to_edit, "indentlevel") <- 1
Hao Zhu62cdde52017-05-20 22:16:03 -040089 } else {
Alan Butlerc81c1fe2018-01-30 11:16:18 -070090 indentLevel <- as.numeric(xml_attr(node_to_edit, "indentlevel"))
Hao Zhu62cdde52017-05-20 22:16:03 -040091 xml_attr(node_to_edit, "style") <- sub(
92 paste0("padding-left: ", indentLevel * 2, "em;"),
93 paste0("padding-left: ", (indentLevel + 1) * 2, "em;"),
94 xml_attr(node_to_edit, "style")
95 )
Alan Butlerc81c1fe2018-01-30 11:16:18 -070096 xml_attr(node_to_edit, "indentlevel") <- indentLevel + 1
Hao Zhu62cdde52017-05-20 22:16:03 -040097 }
98 }
Hao Zhuf2dfd142017-07-24 14:43:28 -040099 out <- as_kable_xml(kable_xml)
Hao Zhu62cdde52017-05-20 22:16:03 -0400100 attributes(out) <- kable_attrs
Hao Zhuf2100832018-01-11 16:20:29 -0500101 if (!"kableExtra" %in% class(out)) class(out) <- c("kableExtra", class(out))
Hao Zhu62cdde52017-05-20 22:16:03 -0400102 return(out)
103}