Pkgdown: Multi-level table of contents

Created on 2 Jul 2019  路  5Comments  路  Source: r-lib/pkgdown

It seems to be a good idea to visually display the document's nested structure created with headers of different order (h1, h2, etc.). Maybe this comment was about this feature, but I decided to create a separate issue.
Current pkgdown version can include headers of different depth, but they all "blend" together, which makes it harder to visually see an article's structure.

I recently discovered a way to deal with this situation:

  • Post-process created html pages with ToC by adding "toc-lev{x}" class to ToC elements, where "{x}" represents the level of entry (1 is the highest; second is nested into first; etc.). Solution is a little bit "hacky", which uses the way ToC is currently created for articles with nested sections:

Code for modification of one html file based on its path

add_toc_levels <- function(path) {
  page <- xml2::read_html(path)

  toc_items <- page %>%
    # Find table of contents by id
    xml2::xml_find_first(xpath = "//*[@id='tocnav']") %>%
    # Find all <li> (list elements) with "linkable" descendants which are
    # assumed to represent TOC entries
    xml2::xml_find_all(xpath = "descendant::li[descendant::a[@href]]")

  # Compute levels of entries by counting number of ancestors with class "nav-stacked":
  # they represent headers, into which current entry is nested
  toc_level <- vapply(toc_items, function(item) {
    xml2::xml_find_all(
      item, xpath = "ancestor::*[contains(@class, 'nav-stacked')]"
    ) %>%
      length()
  }, numeric(1))

  toc_class <- paste0("toc-lev", toc_level)

  # Add appropriate classes
  lapply(seq_along(toc_items), function(i) {
    xml2::xml_set_attr(toc_items[i], attr = "class", value = toc_class[i])
  })

  xml2::write_html(page, path)
}

  • Add CSS rules for those classes to visually separate different levels. For example, padding-left: 20px; for "toc-lev2", padding-left: 40 px; for "toc-lev3", etc. This will create "tabbed" structure.

If you think this solution can live in pkgdown, let me know and I'll gladly make a PR.

feature front end wip

All 5 comments

Can you generate a preview of how this change would impact the pkgdown site on netlify?

This is how current version of pkgdown deals with multilevel ToC (with toc: depth: 3 in '_pkgdown.yml'): https://ecstatic-aryabhata-398322.netlify.com/articles/multileveltoc
And this is how it looks after adding "toc-lev{x}" classes and using mentioned CSS rules: https://fervent-albattani-6211ca.netlify.com/articles/multileveltoc

To be honest the TOC in pkgdown is really lacking. The standard tocify TOC and styles that the regular Rmarkdown creates was great. It collapses and expands as necessary. And it's slick and smooth. Here is an example.

This example here is even better and I see it as an improvement. All the extra elements are removed and the TOC is visually simplified. It is possible to get very close to this simply by playing around with the CSS of the first example.

817

The monocle site uses bootstrap-toc. Unfortunately it's not available on cdnjs.

Resolved by #1111

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mjsteinbaugh picture mjsteinbaugh  路  7Comments

nschiett picture nschiett  路  6Comments

Fazendaaa picture Fazendaaa  路  9Comments

jeffwong picture jeffwong  路  9Comments

ms609 picture ms609  路  6Comments