Add missing variable in templates regarding toc (#127)

Related to #123 and alignement with `html_document()` behavior
diff --git a/DESCRIPTION b/DESCRIPTION
index 797f81c..b780b5a 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -33,8 +33,11 @@
 Imports:
     rmarkdown (>= 1.7)
 Suggests:
+    xfun (>= 0.21),
+    xml2,
     bslib,
-    testthat (>= 3.0.0)
+    testthat (>= 3.0.0),
+    withr (>= 2.4.2)
 Encoding: UTF-8
 Roxygen: list(markdown = TRUE)
 RoxygenNote: 7.1.2
diff --git a/R/revealjs_presentation.R b/R/revealjs_presentation.R
index 12edafc..94e21e6 100644
--- a/R/revealjs_presentation.R
+++ b/R/revealjs_presentation.R
@@ -64,6 +64,8 @@
 revealjs_presentation <- function(incremental = FALSE,
                                   center = FALSE,
                                   slide_level = 2,
+                                  toc = FALSE,
+                                  toc_depth = 3,
                                   fig_width = 8,
                                   fig_height = 6,
                                   fig_retina = if (!fig_caption) 2,
@@ -88,6 +90,9 @@
 
   # base pandoc options for all reveal.js output
   args <- c()
+  
+  # table of contents
+  args <- c(args, pandoc_toc_args(toc, toc_depth))
 
   # template path and assets
   if (identical(template, "default")) {
diff --git a/R/utils.R b/R/utils.R
index 52381a2..7251cff 100644
--- a/R/utils.R
+++ b/R/utils.R
@@ -27,4 +27,4 @@
     }
   }
   pandoc_variable_arg(option, value)
-}
\ No newline at end of file
+}
diff --git a/inst/rmarkdown/templates/revealjs_presentation/resources/default.html b/inst/rmarkdown/templates/revealjs_presentation/resources/default.html
index 4a7ef29..9729ed4 100644
--- a/inst/rmarkdown/templates/revealjs_presentation/resources/default.html
+++ b/inst/rmarkdown/templates/revealjs_presentation/resources/default.html
@@ -549,7 +549,12 @@
 $endif$
 $if(toc)$
 <section id="$idprefix$TOC">
+<nav role="doc-toc">
+$if(toc-title)$
+<h2 id="$idprefix$toc-title">$toc-title$</h2>
+$endif$
 $toc$
+</nav>
 </section>
 $endif$
 
diff --git a/man/revealjs_presentation.Rd b/man/revealjs_presentation.Rd
index e89753d..4aed888 100644
--- a/man/revealjs_presentation.Rd
+++ b/man/revealjs_presentation.Rd
@@ -8,6 +8,8 @@
   incremental = FALSE,
   center = FALSE,
   slide_level = 2,
+  toc = FALSE,
+  toc_depth = 3,
   fig_width = 8,
   fig_height = 6,
   fig_retina = if (!fig_caption) 2,
@@ -45,6 +47,11 @@
 building vertically. It is not recommended that you use deeper nesting of
 section levels with reveal.js.}
 
+\item{toc}{\code{TRUE} to include a table of contents in the output (only
+level 1 headers will be included in the table of contents).}
+
+\item{toc_depth}{Depth of headers to include in table of contents}
+
 \item{fig_width}{Default width (in inches) for figures}
 
 \item{fig_height}{Default height (in inches) for figures}
diff --git a/tests/testthat/helpers.R b/tests/testthat/helpers.R
new file mode 100644
index 0000000..ce5d6c4
--- /dev/null
+++ b/tests/testthat/helpers.R
@@ -0,0 +1,49 @@
+local_temp_rmd_file <- function(..., .env = parent.frame()) {
+  path <- withr::local_tempfile(.local_envir = .env, fileext = ".Rmd")
+  xfun::write_utf8(c(...), path)
+  path
+}
+
+local_temp_draft <- function(.env = parent.frame()) {
+  path <- withr::local_tempfile(.local_envir = .env, fileext = ".Rmd")
+  # TODO: Use `rmarkdown::draft()` when rmarkdown 2.12 is out.  
+  pkg_file <- getFromNamespace("pkg_file", "rmarkdown")
+  template_path <- pkg_file("rmarkdown", "templates", "revealjs_presentation", 
+                            package = "revealjs")
+  rmarkdown::draft(path, template_path, edit = FALSE)
+}
+
+.render_and_read <- function(input, xml = TRUE, ...) {
+  skip_if_not_pandoc()
+  output_file <- withr::local_tempfile(fileext = ".html")
+  res <- rmarkdown::render(input, output_file = output_file, quiet = TRUE, ...)
+  if (xml) {
+    xml2::read_html(res)
+  } else {
+    xfun::read_utf8(res)
+  }
+}
+
+# Use to test pandoc availability or version lower than
+skip_if_not_pandoc <- function(ver = NULL) {
+  if (!pandoc_available(ver)) {
+    msg <- if (is.null(ver)) {
+      "Pandoc is not available"
+    } else {
+      sprintf("Version of Pandoc is lower than %s.", ver)
+    }
+    skip(msg)
+  }
+}
+
+# Use to test version greater than
+skip_if_pandoc <- function(ver = NULL) {
+  if (pandoc_available(ver)) {
+    msg <- if (is.null(ver)) {
+      "Pandoc is available"
+    } else {
+      sprintf("Version of Pandoc is greater than %s.", ver)
+    }
+    skip(msg)
+  }
+}
\ No newline at end of file
diff --git a/tests/testthat/test-revealjs_presentation.R b/tests/testthat/test-revealjs_presentation.R
new file mode 100644
index 0000000..ade1c9a
--- /dev/null
+++ b/tests/testthat/test-revealjs_presentation.R
@@ -0,0 +1,20 @@
+test_that("toc argument works", {
+  skip_if_not_pandoc()
+  skip_if_not_installed("xml2")
+  rmd <- local_temp_draft()
+  html <- .render_and_read(
+    rmd,
+    output_options = list(
+      toc = TRUE,
+      pandoc_args = c(pandoc_variable_arg("toc-title", "TOC"))
+    )
+  )
+  toc <- xml2::xml_find_all(html, "//section[@id='TOC']")
+  expect_length(toc, 1)
+  expect_equal(
+    xml2::xml_text(
+      xml2::xml_find_all(toc, "./nav/*[contains(@id, 'toc-title')]")
+    ),
+    "TOC"
+  )
+})