Skip to content

Moonbase59/gh-toc

 
 

Repository files navigation

gh-toc 

Quickly create Table-of-Content Markdown for GitHub Markdown files.

gh-toc-no-border.png

Table of Contents (made with gh-toc)

Overview 

I could never find a do-it-all, easy to use, online Table-of-Content maker for GitHub (and other) Markdown files. There were many solutions that required downloading or installing something on my computer. For such a trivial task I felt that was unnecessary.

Indeed. This began as a fork and has meanwhile evolved to a full-fledged solution:

  • Full Unicode support, all international characters.
  • Better handling of (hopefully) all underscore cases.
  • Correct handling of code with backticks ` inside.
  • Much better code block support (indented, backticks, tildes, different number of backticks/tildes).
  • YAML/Jekyll/LaTeX front matter support.
  • Optional output of the full Markdown file instead of just the ToC. ToC inserted between <!-- ToC begin --> and <!-- ToC end --> HTML comments, or at [TOP]. You can insert the ToC multiple times, although I don’t see a use case for that.
  • GitHub, HTML and Pandoc/PHP Markdown Extra-compatible anchor generation for easy navigation.
  • Optional backlink generation, to either Top or Table of Contents.
  • Optional use of id instead of name attribute in generated HTML anchors.
  • Automatic cleanup of HTML anchor & backlink code left over from previous runs. That means you can now input a file from a previous run with anchors & backlinks, and output it again without.

None of your data is transferred to the Internet. All work happens in your browser, using JavaScript.

I did lots of testing, rewrote the link generation and added extra functionality, to be as compatbile with GitHub (and others) as possible. And then some. It works great, even for difficult cases.

Note gh-toc works with ATX-type headings (###). It doesn’t try to parse for Setext (===/---) or HTML (<h3>) headings.

No other online ToC-Generator I could find handled all the test cases below correctly!

Test file 

testing.md is a sample Markdown file with many test cases. Copy its contents into the input box of gh-toc to see what gets generated.

Conversion to HTML, using auto-generated HTML anchors 

This syntax is compatible with GitHub and almost anything that generates HTML from Markdown, but the HTML is slightly harder to read. You can select if you want name= (default) or id= HTML anchors generated.

It will generate HTML anchors of the form

# <a name="gh-toc"></a>gh-toc

in the Markdown file, which Pandoc then converts to this HTML:

<h1><a name="gh-toc"></a>gh-toc</h1>
  1. Copy-paste the contents of testing.md into the left input box of gh-toc.
  2. Select
    • Minimum heading level: 1
    • Maximum heading level: 6
    • Full MD: ☑
    • Anchors: HTML
    • BL: ⇧ToC (or any other)
    • Use id: ☐
  3. Click TOC it! and watch the magic.
  4. Copy-paste the contents of the right input box into a text editor and save as testing-html-anchors.md.
  5. Convert to HTML using Pandoc:
    pandoc -s -f markdown-auto_identifiers+yaml_metadata_block -t html testing-html-anchors.md -o testing-html-anchors.html
  6. Open testing-html-anchors.html in your favourite browser and test the links.

Or watch the generated testing-html-anchors.md on GitHub—it works beautifully here. No more endless scrolling in README.md files!

Voilà. Enjoy!

Conversion to HTML, using auto-generated {#…} anchors 

This syntax is compatible with Pandoc and PHP Markdown Extra, for example.

It will generate header attributes of the form

# gh-toc {#gh-toc}

in the Markdown file, which Pandoc then converts to this HTML:

<h1 id="gh-toc">gh-toc</h1>
  1. Copy-paste the contents of testing.md into the left input box of gh-toc.
  2. Select
    • Minimum heading level: 1
    • Maximum heading level: 6
    • Full MD: ☑
    • Anchors: {#…}
    • BL: —
    • Use id: ☐
  3. Click TOC it! and watch the magic.
  4. Copy-paste the contents of the right input box into a text editor and save as testing-curly-anchors.md.
  5. Convert to HTML using Pandoc:
    pandoc -s -f markdown+yaml_metadata_block -t html testing-curly-anchors.md -o testing-curly-anchors.html
  6. Open testing-curly-anchors.html in your favourite browser and test the links. This example intentionally has no backlinks. Compare with the HTML anchors example and you’ll see how much you miss them!

Voilà again!

More features 

Also try the other options, like auto-generated backlinks to ⇧Top or ⇧ToC next to each heading! Backlinks use CSS classes goTop and goToc, so you can even style them!

Generated Markdown using Anchors: HTML and BL: ⇧ToC

# <a name="gh-toc"></a>gh-toc <a href="#toc" class="goToc">⇧</a>

Generated Markdown using Anchors: {#…} and BL: ⇧ToC

# gh-toc <a href="#toc" class="goToc">⇧</a> {#gh-toc}

From simple Table of Contents… 

screenshot-simple-toc

… to full-fledged Markdown with anchors and backlinks! 

screenshot-fullMD-curly-bl

Warning if ToC cannot be inserted into full Markdown 

screenshot-warning

Styling the backlinks with CSS 

Yes, you can! Generated backlinks use the classes goToc and goTop, respectively. The testing.md document includes my really wild example gh-toc.css so you can see the effects possible.

A simpler approach might be just setting the up arrows to 50% opacity and remove the link underlines:

/* An example for styling the backlinks.
 * 
 * Let’s make them 50% opaque and remove the link underline.
 * 
 */

.goToc {
    text-decoration: none;
    opacity: 0.5;
}

.goTop {
    text-decoration: none;
    opacity: 0.5;
}

The evolution of a "simple" tool 

It all started out because I looked for a quick way to generate a GitHub README Table-of-Contents. Looking around, most solutions required installing some software my system. No problem so far, but I work on a lot of machines, different operating systems and all. So it would never simply be available.

Ok, a web page it should be. Accessible everywhere, and simple. Copy-paste is no witchcraft, after all: Ctrl+A, Ctrl+C for copy, then Ctrl+A, Ctrl+V to paste back.

Looking around, I liked IMTheNachoMan’s nGitHubTOC best, but quickly stumbled upon problems with it: Code block and underline issues, for instance. Then I currently live in Germany, and we have some funny characters like äöüßÄÖÜ. Oh yes, and now the capital . Which didn’t work. At least it didn’t generate anchors that would work in GitHub.

So I decided to fork the project and fix some bugs… And the story began.

I looked at the code and tried to reverse-engineer how GitHub generate their anchors (which work really well and have great Unicode support). After setting up test cases, from my own documents, and then some more, I found the original structure of the program to be good, but it needed intensive polishing-up to handle lots of Markdown quirks and special cases.

You can look up my commits to follow what I did, if you like. It took a few days until it really did what I wanted.

Now, as it worked with the basics, and had a good structure, I started thinking options. Rabbit hole, know that? What if I wouldn’t need to copy-paste and insert the ToC manually, but it would auto-insert it for me? And output the complete Markdown? FullMD was born.

Oops, it messed up my long LaTeX front matter! Oh, and I’d use that for dates and versions, too. And Jekyll. I was so tired of seeing H1 level front matter comments! So let’s create front matter handling.

Some people in various forums had hot discussions about whether to use name or id in HTML anchors. Hmm… Why not have an option to switch between these?

Talking anchors, why not include an automatic anchor for the ToC (because I always forgot to). While we’re at it, think of people wanting to go to the Top of the document, too. (Auto-generated when you use BL: ⇧Top.)

Not everything is GitHub. So let’s use the GitHub anchors and find a way to include anchors on the actual headings when not using GitHub (they do it automatically when previewing Markdown files). It actually took a while, and lots of reading and testing, to find a way that would work "everywhere", from GitHub to Pandoc-generated HTML, because Markdown doesn’t support it natively. Fortunately it does support using HTML code, so the most compatible way could be found. Anchor was created. You can switch between no anchors, HTML, and the curly bracket notation.

Now what frustrates me and others most when reading my ultralong READMEs? Right! Not being able to jump back to the Table of Contents! We’re creating anchors anyway, so why not add a backlink feature? Now this should work with minimal or no effort, and both on GitHub and files that are later post-processed into HTML. It should be unobtrusive, like the little up-arrow many web pages show nowadays to go to ⇧Top. Oh, and stylable using CSS. And hey, why not let me choose between ⇧Top and ⇧Toc jumping? What I eventually liked best was a little stylable up-arrow at the right end of each heading, technically inside the heading. And of course the BL (backlink) selection.

I’m so awfully happy. I can now copy-paste my README into gh-toc, select options, and out comes a readily-usable, linked and backlinked file that works. On GitHub and elsewhere.

Oops. Generated all this nice anchor and backlink stuff, uploaded my README, and now need to change it and output it without anchors and backlinks. And gh-toc would leave the old stuff all in! Okay, next step: Auto-cleanup of artifacts left over from previous runs! This works even on headings you don’t touch this time. Let’s say you output heading levels 1–6 last time, generating anchors and backlinks for them, and now you only want to output levels 2–6. Normally, gh-toc will only touch as few of your Markdown code lines as possible, but in this case it makes sense to also remove the now-obsolete level 1 anchors & backlinks from the previous run.

Now I’m really happy. Until I find the next feature, that is…

I love CSS. And I’d maybe like a little symbol better than the arrow. Hmm. Unicode (currently) has no symbol for an unordered list, so let’s create one, gh-toc.svg. But then, how to get that into CSS? A little CSS hacking might be possible, after all… Let’s show how I’ve done it, and include the sample CSS in the HTML example.

Q.E.D.: Anything goes with CSS!

And now you know the rest of the story! (So far.)

Known problems 

  • gh-toc will "brute-force replace" all text between the ToC start marker <!-- ToC begin --> and the end marker <!-- ToC end --> with the new Table of Contents, even if they are in a code block. Avoid that for now, or don’t use the Full MD option in this case and insert the ToC manually. Now fixed and ToC inserting/replacing is safe, even if the "ToC begin/end" comments are out of sequence or one is missing. An alert will pop up if none are found and the ToC cannot be inserted in FullMD mode.

  • Selecting FullMD + Anchor: {#…} will overwrite other than anchor definitions within the curly braces, i.e. {#anchor .red}{#new-anchor}. Selecting Anchor: – (None) doesn’t modify existing curly brace definitions.

The Real Magic 

https://moonbase59.github.io/gh-toc/

Releases

No releases published

Packages

No packages published

Languages

  • HTML 80.5%
  • JavaScript 17.1%
  • CSS 2.4%