blob: 33ad6f710298aa67510848a02c3dffa964c3e34a [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")) {
18 message("Currently generic markdown table using pandoc is not supported.")
19 return(kable_input)
20 }
21 if (kable_format == "html") {
Hao Zhu62cdde52017-05-20 22:16:03 -040022 return(add_indent_html(kable_input, positions))
Hao Zhu8f417202017-05-20 16:37:14 -040023 }
24 if (kable_format == "latex") {
25 return(add_indent_latex(kable_input, positions))
26 }
27}
28
Hao Zhu62cdde52017-05-20 22:16:03 -040029# Add indentation for LaTeX
Hao Zhu8f417202017-05-20 16:37:14 -040030add_indent_latex <- function(kable_input, positions) {
Hao Zhud972e7f2017-05-22 13:27:15 -040031 table_info <- magic_mirror(kable_input)
Hao Zhu8f417202017-05-20 16:37:14 -040032
Hao Zhu8f417202017-05-20 16:37:14 -040033 if (max(positions) > table_info$nrow - 1) {
34 stop("There aren't that many rows in the table. Check positions in ",
35 "add_indent_latex.")
36 }
37
38 out <- kable_input
39 for (i in positions) {
40 rowtext <- table_info$contents[i + 1]
41 out <- sub(rowtext, latex_indent_unit(rowtext), out)
42 }
43 return(out)
44}
45
46latex_indent_unit <- function(rowtext) {
47 paste0("\\\\hspace{1em}", rowtext)
48}
Hao Zhu62cdde52017-05-20 22:16:03 -040049
50# Add indentation for HTML
51add_indent_html <- function(kable_input, positions) {
52 kable_attrs <- attributes(kable_input)
53
54 kable_xml <- read_xml(as.character(kable_input), options = "COMPACT")
55 kable_tbody <- xml_tpart(kable_xml, "tbody")
56
57 group_header_rows <- attr(kable_input, "group_header_rows")
58 if (!is.null(group_header_rows)) {
59 positions <- positions_corrector(positions, group_header_rows,
60 length(xml_children(kable_tbody)))
61 }
62 for (i in positions) {
63 node_to_edit <- xml_child(xml_children(kable_tbody)[[i]], 1)
64 if (!xml_has_attr(node_to_edit, "indentLevel")) {
65 xml_attr(node_to_edit, "style") <- paste(
66 xml_attr(node_to_edit, "style"), "padding-left: 2em;"
67 )
68 xml_attr(node_to_edit, "indentLevel") <- 1
69 } else {
70 indentLevel <- as.numeric(xml_attr(node_to_edit, "indentLevel"))
71 xml_attr(node_to_edit, "style") <- sub(
72 paste0("padding-left: ", indentLevel * 2, "em;"),
73 paste0("padding-left: ", (indentLevel + 1) * 2, "em;"),
74 xml_attr(node_to_edit, "style")
75 )
76 xml_attr(node_to_edit, "indentLevel") <- indentLevel + 1
77 }
78 }
79 out <- structure(as.character(kable_xml), format = "html",
80 class = "knitr_kable")
81 attributes(out) <- kable_attrs
82 return(out)
83}