blob: dc54067bae7c2b45ffdf08b3d9bb07bfb4dbf721 [file] [log] [blame]
Hao Zhudb04e302015-11-15 16:57:38 -05001#' Magic mirror that returns kable's attributes
2#'
Hao Zhuf7994dd2017-02-27 16:58:42 -05003#' @description Mirror mirror tell me, how does this kable look like?
4#'
5#' @param kable_input The output of kable
Hao Zhu78e61222017-05-24 20:53:35 -04006#'
7#' @examples magic_mirror(knitr::kable(head(mtcars), "html"))
Hao Zhudb04e302015-11-15 16:57:38 -05008#' @export
9
Hao Zhuf7994dd2017-02-27 16:58:42 -050010magic_mirror <- function(kable_input){
Hao Zhu32f43f72017-06-20 18:24:54 -040011 if ("kable_meta" %in% names(attributes(kable_input))) {
12 return(attr(kable_input, "kable_meta"))
Hao Zhu9b45a182017-02-27 18:17:46 -050013 }
Hao Zhuf7994dd2017-02-27 16:58:42 -050014 kable_format <- attr(kable_input, "format")
15 if (kable_format == "latex") {
Hao Zhu24bf30c2019-01-22 02:14:33 -050016 table_info <- magic_mirror_latex(kable_input)
Hao Zhudb04e302015-11-15 16:57:38 -050017 }
Hao Zhuf7994dd2017-02-27 16:58:42 -050018 if (kable_format == "html") {
Hao Zhu24bf30c2019-01-22 02:14:33 -050019 table_info <- magic_mirror_html(kable_input)
Hao Zhudb04e302015-11-15 16:57:38 -050020 }
Hao Zhu24bf30c2019-01-22 02:14:33 -050021 return(table_info)
Hao Zhudb04e302015-11-15 16:57:38 -050022}
23
Hao Zhu953f3bd2017-07-28 11:43:40 -040024# Magic mirror for latex tables --------------
Hao Zhuf7994dd2017-02-27 16:58:42 -050025magic_mirror_latex <- function(kable_input){
Hao Zhu24bf30c2019-01-22 02:14:33 -050026 table_info <- list(tabular = NULL, booktabs = FALSE, align = NULL,
Hao Zhuc05e1812017-02-25 01:45:35 -050027 valign = NULL, ncol = NULL, nrow = NULL, colnames = NULL,
Hao Zhud57c2d72017-08-16 22:51:17 -040028 rownames = NULL, caption = NULL, caption.short = NULL,
29 contents = NULL,
Hao Zhuc05e1812017-02-25 01:45:35 -050030 centering = FALSE, table_env = FALSE)
Hao Zhu4adea852015-11-16 16:38:34 -050031 # Tabular
Hao Zhu24bf30c2019-01-22 02:14:33 -050032 table_info$tabular <- ifelse(
Hao Zhuf7994dd2017-02-27 16:58:42 -050033 grepl("\\\\begin\\{tabular\\}", kable_input),
Hao Zhu4adea852015-11-16 16:38:34 -050034 "tabular", "longtable"
Hao Zhudb04e302015-11-15 16:57:38 -050035 )
Hao Zhu4adea852015-11-16 16:38:34 -050036 # Booktabs
Hao Zhu24bf30c2019-01-22 02:14:33 -050037 table_info$booktabs <- grepl("\\\\toprule", kable_input)
Hao Zhu4adea852015-11-16 16:38:34 -050038 # Align
Hao Zhu24bf30c2019-01-22 02:14:33 -050039 table_info$align <- gsub("\\|", "", str_match(
Hao Zhubff01912017-05-23 18:05:00 -040040 kable_input, paste0("\\\\begin\\{",
Hao Zhu24bf30c2019-01-22 02:14:33 -050041 table_info$tabular,"\\}.*\\{(.*?)\\}"))[2])
42 table_info$align_vector <- unlist(strsplit(table_info$align, ""))
43 table_info$align_vector_origin <- table_info$align_vector
Hao Zhuc05e1812017-02-25 01:45:35 -050044 # valign
Hao Zhu24bf30c2019-01-22 02:14:33 -050045 table_info$valign <- gsub("\\|", "", str_match(
46 kable_input, paste0("\\\\begin\\{", table_info$tabular,"\\}(.*)\\{.*?\\}"))[2])
47 table_info$valign2 <- sub("\\[", "\\\\[", table_info$valign)
48 table_info$valign2 <- sub("\\]", "\\\\]", table_info$valign2)
49 table_info$valign3 <- sub("\\[", "", table_info$valign)
50 table_info$valign3 <- sub("\\]", "", table_info$valign3)
51 table_info$begin_tabular <- paste0("\\\\begin\\{", table_info$tabular, "\\}",
52 table_info$valign2)
53 table_info$end_tabular <- paste0("\\\\end\\{", table_info$tabular, "\\}")
Hao Zhu4adea852015-11-16 16:38:34 -050054 # N of columns
Hao Zhu24bf30c2019-01-22 02:14:33 -050055 table_info$ncol <- nchar(table_info$align)
Hao Zhu4adea852015-11-16 16:38:34 -050056 # Caption
Hao Zhud57c2d72017-08-16 22:51:17 -040057 if (str_detect(kable_input, "caption\\[")) {
Hao Zhu70b89b12017-08-19 14:52:55 -040058 caption_line <- str_match(kable_input, "\\\\caption(.*)\\n")[2]
Hao Zhu24bf30c2019-01-22 02:14:33 -050059 table_info$caption.short <- str_match(caption_line, "\\[(.*?)\\]")[2]
60 table_info$caption <- substr(caption_line,
61 nchar(table_info$caption.short) + 4,
qifei8743c772017-08-30 21:20:34 +020062 nchar(caption_line))
Hao Zhud57c2d72017-08-16 22:51:17 -040063 } else {
Hao Zhu24bf30c2019-01-22 02:14:33 -050064 table_info$caption <- str_match(kable_input, "caption\\{(.*?)\\n")[2]
Hao Zhud57c2d72017-08-16 22:51:17 -040065 }
Hao Zhu24bf30c2019-01-22 02:14:33 -050066 if (table_info$tabular == "longtable") {
67 table_info$caption <- str_sub(table_info$caption, 1, -4)
Hao Zhud57c2d72017-08-16 22:51:17 -040068 } else {
Hao Zhu24bf30c2019-01-22 02:14:33 -050069 table_info$caption <- str_sub(table_info$caption, 1, -2)
Hao Zhud57c2d72017-08-16 22:51:17 -040070 }
Hao Zhu4adea852015-11-16 16:38:34 -050071 # Contents
Hao Zhu24bf30c2019-01-22 02:14:33 -050072 table_info$contents <- str_match_all(kable_input, "\n(.*)\\\\\\\\")[[1]][,2]
73 table_info$contents <- regex_escape(table_info$contents, T)
74 if (table_info$tabular == "longtable" & !is.na(table_info$caption) &
Hao Zhud384bc22018-05-12 22:24:30 -040075 !str_detect(kable_input, "\\\\begin\\{table\\}\\n\\n\\\\caption")) {
Hao Zhu24bf30c2019-01-22 02:14:33 -050076 table_info$contents <- table_info$contents[-1]
Hao Zhua3fc0c42017-02-27 12:04:59 -050077 }
Hao Zhud384bc22018-05-12 22:24:30 -040078 if (!is.null(attr(kable_input, "n_head"))) {
79 n_head <- attr(kable_input, "n_head")
Hao Zhu24bf30c2019-01-22 02:14:33 -050080 table_info$new_header_row <- table_info$contents[seq(n_head - 1, 1)]
81 table_info$contents <- table_info$contents[-seq(1, n_head - 1)]
82 table_info$header_df <- extra_header_to_header_df(table_info$new_header_row)
83 table_info$new_header_row <- paste0(table_info$new_header_row, "\\\\\\\\")
Hao Zhud384bc22018-05-12 22:24:30 -040084 }
Hao Zhu24bf30c2019-01-22 02:14:33 -050085 table_info$nrow <- length(table_info$contents)
86 table_info$duplicated_rows <- (sum(duplicated(table_info$contents)) != 0)
Hao Zhu4adea852015-11-16 16:38:34 -050087 # Column names
Hao Zhu24bf30c2019-01-22 02:14:33 -050088 if (table_info$booktabs & !grepl("\\\\midrule", kable_input)) {
89 table_info$colnames <- NULL
90 table_info$position_offset <- 0
Leo83f05132018-05-10 14:12:16 +080091 } else {
Hao Zhu24bf30c2019-01-22 02:14:33 -050092 table_info$colnames <- str_split(table_info$contents[1], " \\& ")[[1]]
93 table_info$position_offset <- 1
Leo83f05132018-05-10 14:12:16 +080094 }
Hao Zhu4adea852015-11-16 16:38:34 -050095 # Row names
Hao Zhu24bf30c2019-01-22 02:14:33 -050096 table_info$rownames <- str_extract(table_info$contents, "^[^ &]*")
Hao Zhuc05e1812017-02-25 01:45:35 -050097
Hao Zhu24bf30c2019-01-22 02:14:33 -050098 table_info$centering <- grepl("\\\\centering", kable_input)
Hao Zhuc05e1812017-02-25 01:45:35 -050099
Hao Zhu24bf30c2019-01-22 02:14:33 -0500100 table_info$table_env <- (!is.na(table_info$caption) &
101 table_info$tabular != "longtable")
Hao Zhud384bc22018-05-12 22:24:30 -0400102
Hao Zhu24bf30c2019-01-22 02:14:33 -0500103 return(table_info)
Hao Zhudb04e302015-11-15 16:57:38 -0500104}
Hao Zhu8977a8a2015-11-19 16:52:21 -0500105
Hao Zhud384bc22018-05-12 22:24:30 -0400106extra_header_to_header_df <- function(extra_header_rows) {
107 lapply(str_split(extra_header_rows, " \\& "), function(x) {
108 as.data.frame(t(sapply(x, extra_header_to_header_df_)), row.names = NA)
109 })
110}
111
112extra_header_to_header_df_ <- function(x) {
113 if (trimws(x) == "") return(c(header = " ", colspan = "1"))
114 x <- trimws(x)
115 x_header <- str_match(x, "([^\\}\\{]*)\\\\\\}$")[2]
116 x_colspan <- str_match(x, "^\\\\\\\\multicolumn\\\\\\{([^\\\\\\}]*)")[2]
117 return(c(header = x_header, colspan = x_colspan))
118}
119
Hao Zhu953f3bd2017-07-28 11:43:40 -0400120# Magic Mirror for html table --------
Hao Zhuf7994dd2017-02-27 16:58:42 -0500121magic_mirror_html <- function(kable_input){
Hao Zhu24bf30c2019-01-22 02:14:33 -0500122 table_info <- list()
Hao Zhu558c72f2017-07-24 15:12:00 -0400123 kable_xml <- read_kable_as_xml(kable_input)
Hao Zhu8977a8a2015-11-19 16:52:21 -0500124 # Caption
Hao Zhu24bf30c2019-01-22 02:14:33 -0500125 table_info$caption <- xml_text(xml_child(kable_xml, "caption"))
Hao Zhu8977a8a2015-11-19 16:52:21 -0500126 # Contents
Hao Zhu24bf30c2019-01-22 02:14:33 -0500127 # table_info$contents <- html_table(read_html(as.character(kable_input)))[[1]]
Hao Zhu8977a8a2015-11-19 16:52:21 -0500128 # colnames
Hao Zhu24bf30c2019-01-22 02:14:33 -0500129 table_info$colnames <- lapply(xml_children(xml_child(kable_xml, "thead")),
Hao Zhuf7994dd2017-02-27 16:58:42 -0500130 xml_children)
Hao Zhu24bf30c2019-01-22 02:14:33 -0500131 table_info$colnames <- table_info$colnames[[length(table_info$colnames)]]
132 table_info$colnames <- trimws(xml_text(table_info$colnames))
133 table_info$ncol <- length(table_info$colnames)
134 table_info$nrow_header <- length(xml_children(xml_child(kable_xml, "thead")))
135 table_info$nrow_body <- nrow(table_info$contents)
136 table_info$table_class <- xml_attr(kable_xml, "class")
137 table_info$table_style <- xml_attr(kable_xml, "style")
138 return(table_info)
Hao Zhu8977a8a2015-11-19 16:52:21 -0500139}
140
Hao Zhu26234122017-02-22 15:34:33 -0500141