Add footnote support to rmarkdown/pandoc
diff --git a/DESCRIPTION b/DESCRIPTION
index d1a356a..38c3907 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -10,11 +10,11 @@
License: MIT + file LICENSE
LazyData: TRUE
Depends:
- R (>= 3.1.2)
+ R (>= 3.1.2),
+ stringr (>= 1.0)
Imports:
knitr (>= 1.10),
- magrittr,
- stringr (>= 1.0)
+ magrittr
Suggests:
testthat
-RoxygenNote: 5.0.0
+RoxygenNote: 5.0.1
diff --git a/NAMESPACE b/NAMESPACE
index 93e01c9..6d17c4a 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,3 +1,4 @@
# Generated by roxygen2: do not edit by hand
export(add_footnote)
+export(magic_mirror)
diff --git a/R/footnote.R b/R/footnote.R
index cca651a..8724141 100644
--- a/R/footnote.R
+++ b/R/footnote.R
@@ -14,7 +14,7 @@
#' "number", "alphabet" and "symbol".
#'
#' @export
-add_footnote <- function(input, label = NULL, notation = "alphabet") {
+add_footnote <- function(input, label = NULL, notation = "alphabet", threeparttable = F) {
if (is.null(label)){return(input)}
# Define available id list
if (!notation %in% c("number", "alphabet", "symbol")){
@@ -35,54 +35,91 @@
"**", "††", "‡‡", "§§", "¶¶",
"*", "†††", "‡‡‡", "§§§", "¶¶¶",
"**", "††††", "‡‡‡‡", "§§§§", "¶¶¶¶"
+ ),
+ symbol.markdown = c(
+ "\\*", "†", "‡", "§", "¶",
+ "\\*\\*", "††", "‡‡", "§§", "¶¶",
+ "\\*\\*\\*", "†††", "‡‡‡", "§§§", "¶¶¶",
+ "\\*\\*\\*\\*", "††††", "‡‡‡‡", "§§§§", "¶¶¶¶"
+ ),
+ symbol.pandoc = c(
+ "\\*", "†", "‡", "§", "¶",
+ "\\*\\*", "††", "‡‡", "§§", "¶¶",
+ "\\*\\*\\*", "†††", "‡‡‡", "§§§", "¶¶¶",
+ "\\*\\*\\*\\*", "††††", "‡‡‡‡", "§§§§", "¶¶¶¶"
)
)
ids <- ids.ops[,notation]
+ ids.intable <- gsub("\\*", "\\\\*", ids)
+
+ #count the number of items in label and intable notation
+ count.label = length(label)
+ count.intablenoot = sum(str_count(input, "\\[note\\]"))
+ if (count.intablenoot != 0 & count.label != count.intablenoot){
+ warning(paste("You entered", count.label, "labels but you put",
+ count.intablenoot, "[note] in your table."))
+ }
if(!attr(input, "format") %in% c("html", "latex")){
- warning("Currently kableExtra only supports html and latex. You have to specify your kable export format or set it in the global option `knitr.table.format`.")
export <- input
+ if(count.intablenoot != 0){
+ for(i in 1:count.intablenoot){
+ export[which(str_detect(export, "\\[note\\]"))[1]] <-
+ sub("\\[note\\]", paste0("^", ids.intable[i], "^",
+ paste0(rep(" ", 4 - nchar(as.character(ids[i]))),
+ collapse = "")), export[which(str_detect(export, "\\[note\\]"))[1]])
+ }
}
- # Generate latex table footnote using threeparttable --------------------------------
+ export[length(export)+1] <- ""
+ export[length(export)+1] <- "__Note:__"
+ export[length(export)+1] <- paste0(
+ paste0("^", ids[1:length(label)], "^ ", label), collapse = " "
+ )
+ }
+
+ # Generate latex table footnote --------------------------------
if(attr(input, "format")=="latex"){
- #count the number of items in label and intable notation
- count.label = length(label)
- count.intablenoot = sum(gregexpr("\\[note\\]", input)[[1]]>0)
- if (count.intablenoot != 0 & count.label != count.intablenoot){
- warning(paste("You entered", count.label, "labels but you put",
- count.intablenoot, "[note] in your table."))
+ # If longtable is used, then use page footnote instead of threeparttable
+ # as it makes more sense to see the footnote at the bottom of page if
+ # table is longer than one page.
+ if(grepl("\\\\begin\\{longtable\\}", input)){
+
+ for(i in 1:count.intablenoot){
+ input <- sub("\\[note\\]", paste0("\\\\footnote[", ids[i], "]{", label[i], "}"), input)
+ }
+ }else{
+ # Regular cases other than longtable
+ # generate footer with appropriate symbol
+ footer <- ""
+ for(i in 1:count.label){
+ footer <- paste0(footer,"\\\\item [", ids[i], "] ", label[i], "\n")
}
- # generate footer with appropriate symbol
- footer <- ""
- for(i in 1:count.label){
- footer <- paste0(footer,"\\\\item [", ids[i], "] ", label[i], "\n")
- }
+ # Replace in-table notation with appropriate symbol
+ for(i in 1:count.intablenoot){
+ input <- sub("\\[note\\]", paste0("\\\\textsuperscript{", ids[i], "}"), input)
+ }
- # Replace in-table notation with appropriate symbol
- for(i in 1:count.intablenoot){
- input <- sub("\\[note\\]", paste0("\\\\textsuperscript{", ids[i], "}"), input)
- }
-
- #
- if(grepl("\\\\caption\\{.*?\\}", input)){
- if(grepl("\\\\begin\\{tabular\\}", input)){
+ if(grepl("\\\\caption\\{.*?\\}", input)){
export <- sub("\\\\caption\\{", "\\\\begin{threeparttable}\n\\\\caption{", input)
- }else{export <- input}
- }else{
- export <- sub("\\\\begin\\{tabular\\}", "\\\\begin{threeparttable}\n\\\\begin{tabular}", input)
- }
- export <- gsub(
+ }else{
+ export <- sub("\\\\begin\\{tabular\\}", "\\\\begin{threeparttable}\n\\\\begin{tabular}", input)
+ }
+ export <- gsub(
"\\\\end\\{tabular\\}",
paste0(
"\\\\end{tabular}\n\\\\begin{tablenotes}\n\\\\small\n",
footer, "\\\\end{tablenotes}\n\\\\end{threeparttable}"
- ),
+ ),
export)
+ }
}
if(attr(input, "format")=="html"){
-
+ export <- input
}
return(export)
}
+
+
+
diff --git a/R/magic_mirror.R b/R/magic_mirror.R
new file mode 100644
index 0000000..0fa726c
--- /dev/null
+++ b/R/magic_mirror.R
@@ -0,0 +1,28 @@
+#' Magic mirror that returns kable's attributes
+#'
+#' @param input The output of kable
+#'
+#' @export
+
+magic_mirror <- function(input){
+ if(!"knitr_kable" %in% attr(input, "format")){
+ warning("magic_mirror may not be able to produce correct result if the",
+ " input table is not rendered by knitr::kable. ")
+ }
+ kable_format <- attr(input, "format")
+ if (kable_format == "latex"){
+ magic_mirror_latex(input)
+ }
+ if (kable_format == "html"){
+ magic_mirror_html(input)
+ }
+}
+
+#' Magic mirror for latex tables
+magic_mirror_latex <- function(input){
+ # kable will put a begin{table} shell if caption is not NULL
+ caption <- ifelse(
+ str_detect(input, "\\\\caption\\{.*?\\}"),
+ str_match(input, "caption\\{(.*?)\\}")[2], NULL
+ )
+}
diff --git a/README.Rmd b/README.Rmd
index dff12ac..9851a02 100644
--- a/README.Rmd
+++ b/README.Rmd
@@ -5,10 +5,10 @@
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
-#Introduction
-If CRAN allows, I really want to call this package `kable%>%`. Well, let's sit down and get back to the reality. Now you have `kableExtra`.
+This package is still in an "as-is" state. You can save a lot of finger-typing time by using it but you still need to understand what is really going on behind the hood, which is still far behind my goal. Also, since the default output format of `kable` is `markdown`, which doesn't support high-level table customization, it may not work well in many cases. I would recommend you to set the `format` option in each `kable` function or to define `options(knitr.table.format = 'html')` or `latex` somewhere in your document.
-Everyone loves `kable`, so do I. It is the most straight forward, convenient table generating function in R (in my opinion). At the same time, it won't through you some useless messages that you need to think of a way to get rid of. Also, if you are planning to "knit" a document, you probably have already have `knitr` loaded. Why would you want to load another "table generator" package if the original one can fulfill your need.
+#Introduction
+`knitr::kable` wins the favor of a lot of people, including me, by its ultimate simplicity.
Even though there are some other available packages in `R` to build beautiful tables, `kable` is still my go-to function whenever I want to build a table in `rmarkdown` or `Shiny`. After using `kable` for a long time, I can see the only reason that prevents people from using `kable` is its simplicityThis package is designed to enhance `kable`'s functionality without destorying its beauty of simplicity by using our favorite `pipe` syntax.
diff --git a/README.md b/README.md
index 4bf0dd5..f6c7668 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,6 @@
<!-- README.md is generated from README.Rmd. Please edit that file -->
+This package is still in an "as-is" state. You can save a lot of finger-typing time by using it but you still need to understand what is really going on behind the hood. Also, since the default output format of `kable` is `markdown`, which doesn't support high-level table customization, it may not work well in many cases. I would recommend you to set the `format` option in `kable` or to define `options(knitr.table.format = 'html')` or `latex` somewhere in your document. \#Introduction My previous package `ezsummary` was trying to fulfill
+
+Everyone loves `kable`, so do I. It is the most straight forward, convenient table generating function in R (in my opinion). At the same time, it won't through you some useless messages that you need to think of a way to get rid of. Also, if you are planning to "knit" a document, you probably have already have `knitr` loaded. Why would you want to load another "table generator" package if the original one can fulfill your need.
+
+Even though there are some other available packages in `R` to build beautiful tables, `kable` is still my go-to function whenever I want to build a table in `rmarkdown` or `Shiny`. After using `kable` for a long time, I can see the only reason that prevents people from using `kable` is its simplicityThis package is designed to enhance `kable`'s functionality without destorying its beauty of simplicity by using our favorite `pipe` syntax.
diff --git a/man/magic_mirror.Rd b/man/magic_mirror.Rd
new file mode 100644
index 0000000..e2c531e
--- /dev/null
+++ b/man/magic_mirror.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/magic_mirror.R
+\name{magic_mirror}
+\alias{magic_mirror}
+\title{Magic mirror that returns kable's attributes}
+\usage{
+magic_mirror(input)
+}
+\arguments{
+\item{input}{The output of kable}
+}
+\description{
+Magic mirror that returns kable's attributes
+}
+
diff --git a/man/magic_mirror_latex.Rd b/man/magic_mirror_latex.Rd
new file mode 100644
index 0000000..8a2f0f3
--- /dev/null
+++ b/man/magic_mirror_latex.Rd
@@ -0,0 +1,12 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/magic_mirror.R
+\name{magic_mirror_latex}
+\alias{magic_mirror_latex}
+\title{Magic mirror for latex tables}
+\usage{
+magic_mirror_latex(input)
+}
+\description{
+Magic mirror for latex tables
+}
+