Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: TOC Stop Depth and Start Depth #5676

Closed
ghost opened this issue Aug 8, 2019 · 6 comments
Closed

Feature Request: TOC Stop Depth and Start Depth #5676

ghost opened this issue Aug 8, 2019 · 6 comments

Comments

@ghost
Copy link

ghost commented Aug 8, 2019

Pandoc supports --toc-depth=NUMBER to limit the number of sections included in the table of contents. As a variation, consider:

--toc-depth-start=2
--toc-depth-stop=4

This would include heading levels 2 through 4 in the table of contents, inclusive, omitting heading levels 1 and 5 and up. This suggests that --toc-depth can be aliased to --toc-depth-stop and the default value for --toc-depth-start would be 1.

@jgm
Copy link
Owner

jgm commented Aug 8, 2019

Why would you want to include heading levels 2-4 but not 1?

@ghost
Copy link
Author

ghost commented Aug 9, 2019

I have a blog series where the H1 is the blog title and H2/H3 are the main headings. The menu at the top of the blog extracts the main heading levels 2 through 3 because the title isn't part of the "contents" per se. (It would be like putting the cover title for a book inside the table of contents.)

typesetting-md

@jgm
Copy link
Owner

jgm commented Aug 9, 2019

Pandoc really wants you to use the title in metadata for the title (this will create a level 1 heading on the page, but also help populate the title tag). Then your top-level headings can be level 1.

You could write a fairly simple lua filter to match on a level 1 header, populate the title in metadata with its contents, and remove it, while demoting other headers by 1 level.

@jgm
Copy link
Owner

jgm commented Aug 9, 2019

See also #5615, which I think is a cleaner solution than making TOC start depth configurable.

@ghost
Copy link
Author

ghost commented Aug 9, 2019

but also help populate the title tag

That is a useful default. In this use case, I'm using fmpp (a FreeMarker template engine preprocessor) to convert a document template to a static HTML document, where the body of the template is created using pandoc, which converts Markdown to an HTML fragment that's included by fmpp:

<#ftl encoding="UTF-8">
<#assign updated = .now>
<!doctype html>
<html lang="en">
<head>
  <title>Markdown Typesetting with Pandoc and ConTeXt Blog Series</title>
  <style>
    <#include "includes/css/main.min.css">

    <#if resource?starts_with( "blog" )>
    <!-- ... -->
    <#if>
</head>
<!-- ... body, main, and other elements ... -->
      <#include "includes/html/body.html" parse=false encoding="UTF-8">
<!-- ... article, footer, and end of body/html ... -->

And have a function, loops over "index.md" files, to convert Markdown into HTML:

convert_markdown() {
  local -r FILE_HTML="$INC_DIR/html/body.html"
  local -r FILE_TOC="$INC_DIR/html/toc.html"
  local -r XPATH="//html/body/nav/ul/*/ul"

  if [[ "${PWD}" == *blog* ]]; then
    echo "<nav class='toc'>" > "${FILE_TOC}"
    pandoc -s --toc "$1" 2> /dev/null | \
      xmllint --html --xpath "${XPATH}" - 2> /dev/null >> "${FILE_TOC}"
    echo "</nav" >> "${FILE_TOC}"
  fi

  pandoc "$1" \
    -f markdown-tex_math_dollars-raw_tex-auto_identifiers+auto_identifiers \
    -o "$FILE_HTML"
}

There's little functional difference between the echo statements above and the suggestion in #5675 to externalize the TOC to a file. In both cases users still must code <nav> elements somewhere, which slightly duplicates pandoc's existing ability to generate <nav> elements. The combination of --toc and --toc-depth-start would simplify the convert_markdown function to a single pandoc call with no external dependencies, such as:

convert_markdown() {
  pandoc "$1" \
    --toc --toc-depth-start=2 \
    -f markdown-tex_math_dollars-raw_tex-auto_identifiers+auto_identifiers \
    -o "$INC_DIR/html/body.html"
}

This would also eliminate the warning that a page title is needed because standalone mode would no longer be necessary (to generate the TOC, external template notwithstanding).

A lua filter is a great idea. I find they often take much more time to write than a couple post-processing calls with command-line tools and result in external files (that then need to be referenced correctly w.r.t. their location). These two lines, sandwiching a pandoc call, for example, strip out the first heading level:

  local -r XPATH="//html/body/nav/ul/*/ul"
      xmllint --html --xpath "${XPATH}" - >> "${FILE_TOC}"

It works, but a start and end depth would be cleaner.

@jgm
Copy link
Owner

jgm commented Aug 9, 2019

Using a custom template to generate the TOC (as I suggested in the other issue) would be cleaner than what you're doing. And using a lua filter as suggested above would be cleaner than using xmllint. This would also give you "no external dependencies", since you don't need to have a lua interpreter to use lua filters.

Anyway, I don't like to multiply our already plentiful command-line options without strong reasons, and in this case I don't see a strong reason other than what might be handled by #5615.

@jgm jgm closed this as completed Aug 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant