Fix the duplicated row bug in LaTeX table. Fix a bug introduced in #73. Change back to div for cell_spec
diff --git a/R/add_indent.R b/R/add_indent.R
index 8932eaa..a0cb37f 100644
--- a/R/add_indent.R
+++ b/R/add_indent.R
@@ -29,13 +29,19 @@
 # Add indentation for LaTeX
 add_indent_latex <- function(kable_input, positions) {
   table_info <- magic_mirror(kable_input)
+  out <- enc2utf8(as.character(kable_input))
+
+  if (table_info$duplicated_rows) {
+    dup_fx_out <- fix_duplicated_rows_latex(out, table_info)
+    out <- dup_fx_out[[1]]
+    table_info <- dup_fx_out[[2]]
+  }
 
   if (max(positions) > table_info$nrow - 1) {
     stop("There aren't that many rows in the table. Check positions in ",
          "add_indent_latex.")
   }
 
-  out <- enc2utf8(kable_input)
   for (i in positions) {
     rowtext <- table_info$contents[i + 1]
     out <- sub(rowtext, latex_indent_unit(rowtext), out, perl = TRUE)
diff --git a/R/cell_spec.R b/R/cell_spec.R
index 7b7f00a..0f55d31 100644
--- a/R/cell_spec.R
+++ b/R/cell_spec.R
@@ -21,8 +21,8 @@
 #' @param font_size Only if you want to specify font size locally in HTML.
 #' This feature is not available in LaTeX
 #' @param angle 0-360, degree that the text will rotate. Can be a vector.
-#' @param hover_message A vector of strings to be displayed as hover message.
-#' Of course, this feature is nly available in HTML.
+#' @param tooltip A vector of strings to be displayed as tooltip.
+#' Of course, this feature is only available in HTML.
 #' @param background_as_tile T/F value indicating if you want to have round
 #' cornered tile as background.
 #'
@@ -31,7 +31,7 @@
                       bold = F, italic = F, monospace = F,
                       color = NULL, background = NULL,
                       align = NULL, font_size = NULL, angle = NULL,
-                      hover_message = NULL, background_as_tile = TRUE) {
+                      tooltip = NULL, background_as_tile = TRUE) {
 
   if (missing(format) || is.null(format)) format = getOption('knitr.table.format')
   if (is.null(format)) {
@@ -42,7 +42,7 @@
   if (tolower(format) == "html") {
     return(cell_spec_html(x, bold, italic, monospace,
                           color, background, align, font_size, angle,
-                          hover_message, background_as_tile))
+                          tooltip, background_as_tile))
   }
   if (tolower(format) == "latex") {
     return(cell_spec_latex(x, bold, italic, monospace,
@@ -52,7 +52,7 @@
 
 cell_spec_html <- function(x, bold, italic, monospace,
                            color, background, align, font_size, angle,
-                           hover_message, background_as_tile) {
+                           tooltip, background_as_tile) {
   cell_style <- NULL
   if (bold) cell_style <- paste(cell_style,"font-weight: bold;")
   if (italic) cell_style <- paste(cell_style, "font-style: italic;")
@@ -84,12 +84,12 @@
                          "deg);")
   }
 
-  if (!is.null(hover_message)) {
-    hover_message <- gsub("\n", "&#013;", hover_message)
-    hover_message <- paste0("data-toggle='tooltip' title='", hover_message, "'")
+  if (!is.null(tooltip)) {
+    tooltip <- gsub("\n", "&#013;", tooltip)
+    tooltip <- paste0("data-toggle='tooltip' title='", tooltip, "'")
   }
   out <- paste0(
-    '<span style="', cell_style, '"', hover_message, '>', x, '</span>'
+    '<div style="', cell_style, '"', tooltip, '>', x, '</div>'
   )
   return(out)
 }
diff --git a/R/collapse_rows.R b/R/collapse_rows.R
index 8ba1250..af2c0a5 100644
--- a/R/collapse_rows.R
+++ b/R/collapse_rows.R
@@ -86,10 +86,18 @@
 
 collapse_rows_latex <- function(kable_input, columns) {
   table_info <- magic_mirror(kable_input)
+  out <- enc2utf8(as.character(kable_input))
+
+  if (table_info$duplicated_rows) {
+    dup_fx_out <- fix_duplicated_rows_latex(out, table_info)
+    out <- dup_fx_out[[1]]
+    table_info <- dup_fx_out[[2]]
+  }
+
   if (is.null(columns)) {
     columns <- seq(1, table_info$ncol)
   }
-  out <- enc2utf8(as.character(kable_input))
+
   contents <- table_info$contents
   kable_dt <- kable_dt_latex(contents)
   collapse_matrix <- collapse_row_matrix(kable_dt, columns, html = F)
diff --git a/R/group_rows.R b/R/group_rows.R
index 0d31bbd..7009995 100644
--- a/R/group_rows.R
+++ b/R/group_rows.R
@@ -117,6 +117,12 @@
   table_info <- magic_mirror(kable_input)
   out <- enc2utf8(as.character(kable_input))
 
+  if (table_info$duplicated_rows) {
+    dup_fx_out <- fix_duplicated_rows_latex(out, table_info)
+    out <- dup_fx_out[[1]]
+    table_info <- dup_fx_out[[2]]
+  }
+
   if (escape) {
     group_label <- escape_latex(group_label)
     group_label <- gsub("\\\\", "\\\\\\\\", group_label)
diff --git a/R/kableExtra-package.R b/R/kableExtra-package.R
index 672eb8d..0e9df80 100644
--- a/R/kableExtra-package.R
+++ b/R/kableExtra-package.R
@@ -68,6 +68,7 @@
 #' @importFrom readr read_lines read_file
 #' @importFrom scales rescale
 #' @importFrom viridisLite viridis
+#' @importFrom stats ave
 #' @name kableExtra-package
 #' @aliases kableExtra
 #' @docType package
diff --git a/R/kable_styling.R b/R/kable_styling.R
index 417c8dd..7555d3e 100644
--- a/R/kable_styling.R
+++ b/R/kable_styling.R
@@ -382,6 +382,7 @@
 
 styling_latex_position <- function(x, table_info, position, latex_options) {
   hold_position <- intersect(c("hold_position", "HOLD_position"), latex_options)
+  if (length(hold_position) == 0) hold_position <- ""
   switch(
     position,
     center = styling_latex_position_center(x, table_info, hold_position),
diff --git a/R/magic_mirror.R b/R/magic_mirror.R
index 66b3fde..e6503b4 100644
--- a/R/magic_mirror.R
+++ b/R/magic_mirror.R
@@ -88,6 +88,7 @@
   if (kable_info$tabular == "longtable" & !is.na(kable_info$caption)) {
     kable_info$contents <- kable_info$contents[-1]
   }
+  kable_info$duplicated_rows <- (sum(duplicated(kable_info$contents)) != 0)
   # Column names
   kable_info$colnames <- str_split(kable_info$contents[1], " \\& ")[[1]]
   # Row names
diff --git a/R/row_spec.R b/R/row_spec.R
index ec8a959..877ab81 100644
--- a/R/row_spec.R
+++ b/R/row_spec.R
@@ -142,6 +142,13 @@
                            color, background, align, angle) {
   table_info <- magic_mirror(kable_input)
   out <- enc2utf8(as.character(kable_input))
+
+  if (table_info$duplicated_rows) {
+    dup_fx_out <- fix_duplicated_rows_latex(out, table_info)
+    out <- dup_fx_out[[1]]
+    table_info <- dup_fx_out[[2]]
+  }
+
   row <- row + 1
   for (i in row) {
     target_row <- table_info$contents[i]
diff --git a/R/sparkline.R b/R/sparkline.R
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/R/sparkline.R
diff --git a/R/util.R b/R/util.R
index dc71524..f63e0c0 100644
--- a/R/util.R
+++ b/R/util.R
@@ -111,3 +111,26 @@
     "\\usepackage{threeparttable}"
   ))
 }
+
+# Fix duplicated rows in LaTeX tables
+fix_duplicated_rows_latex <- function(kable_input, table_info) {
+  # Since sub/string_replace start from beginning, we count unique value from
+  # behind.
+  rev_contents <- rev(table_info$contents)
+  dup_index <- rev(ave(seq_along(rev_contents), rev_contents,
+                       FUN = seq_along))
+  for (i in which(dup_index != 1)) {
+    dup_row <- table_info$contents[i]
+    empty_times <- dup_index[i] - 1
+    new_row <- str_replace(
+      dup_row, "&",
+      paste(c("&", rep("\\\\\\\\empty", empty_times)), collapse = ""))
+    kable_input <- str_replace(kable_input, dup_row, new_row)
+    table_info$contents[i] <- new_row
+  }
+  table_info$duplicated_rows <- FALSE
+  return(list(kable_input, table_info))
+}
+
+
+