Generate table of contents with anchors for markdown file - Vim plugin Jul 20 2020

Vim is my preferred text editor, and I do most of my writing on markdown. If you haven't used markdown, I encourage you to try it out. Markdown is a simple markup language that is in common use on the internet for static site generators. The syntax is easy to remember; that is probably why I prefer it. One useful improvement to our markdown files is the addition of a tabel of contents. Having a table of contents on my documents is handy, but more than just having the table of content being able to navigate to the sections is even better. In this short article, I'll show you how I accomplish this by using my modified version of the vim-markdown-toc plugin.

Let's get started.

Disclaimer make sure you backup your data before you generate the table of content, I tried my best to make the anchors work correctly, but I can't assure you that the code can't cause any loss of data, use the plugin at your own risk.

What we would like from our table of contents

Generating the table of contents is half the battle. When I write my posts, I want the reader (and me) to be able to navigate to each section from the table of contents easily. There are a few plugins to generate the table of content, but I couldn't find one to create the anchors for each section. So, what do we do when we can't find a solution? We built it.

To generate the table of contents, I use the plugin vim-markdown-toc. I forked the project and added the new functionality, I submitted a pull request, but at the time of writing it is still pending. I suggest you use my fork, you can find it here: rderik/vim-markdown-toc.

Let me show you what I would like my table of contents to look like. Let's imagine we have the following markdown file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Introduction

Content

# Section One
Content

# Section two

Content

## Sub-section two - a

Content

# Section three

Content

# Conclusions

Content

After generating my table of contents, I would like to have the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Introduction

Content

* [Section One](#section-one)
* [Section two](#section-two)
  * [Sub-section two - a](#sub-section-two-a)
* [Section three](#section-three)
* [Conclusions](#conclusions)

<a name='section-one'></a>
# Section One
Content

<a name='section-two'></a>
# Section two

Content


<a name='sub-section-two-a'></a>
## Sub-section two - a

Content

<a name='section-three'></a>
# Section three

Content

<a name='conclusions'></a>
#Conclusions

Content

Easy enough. I'm adding the anchor in HTML because my markdowns are translated to HTML in the end, and I want it to work on my website. If you need it in another format this solution won't work without modifying the plugin. You could use pandoc(1) if you don't want to change the plugin.

Ok, let's install and configure my fork of the plugin.

Installing and setup vim-markdown-toc

I use vim-plug to manage my vim plugins, so it's easy to instal the plugin. Add it to your .vimrc file.

1
2
" Create Table of Content form Markdown files
Plug 'rderik/vim-markdown-toc', { 'branch': 'add-anchors-to-headings/drc2r' }

Currently is in the branch add-anchors-to-headings/drc2r. If in the future this changes I'll update the post.

Install the Plugin.

1
:PlugInstall

Now we need to configure the plugin with the following variables:

1
2
3
" Vim markdown Table of Contents
let g:vmt_insert_anchors = 1
let g:vmt_auto_update_on_save = 1

I want my table of contents to update automatically on save, but you can do it manually if you prefer. You will have to delete the current Table of contents and generated again, with the following vim commands.

1
2
:RemoveToc
:GenTocRedcarpet

I use Redcapret as my markdown parser, but the plugin supports others:

That's it. You don't have to do anything else. Let's test it.

Testing the plugin

Create a markdown file, test.md and add the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Introduction

Content

# Section One
Content

# Section two

Content

## Sub-section two - a

Content

# Section three

Content

# Conclusions

Content

We are going to insert our table of contents after the content in the introduction (line 4). Go to that line and run:

1
:GenTocRedcarpet

You'll see that each generated code is wrapped inside comments:

1
2
3
<!- - vim-markdown-toc Redcarpet -->
...
<!- - vim-markdown-toc -->

The plugin needs this to identify the data it generates so it can delete it and updated it without confusion.

Ok, that's it. There you have it an easy to use table-of-content-generator for vim, that includes anchors.

Final thoughts

I hope this feature is useful for you as much as it is for me. Makes my writing process easier, and it was fun to code it. If you think someone else would benefit from it, please share. And as always, feedback is welcomed.


** If you want to check what else I'm currently doing, be sure to follow me on twitter @rderik or subscribe to the newsletter. If you want to send me a direct message, you can send it to derik@rderik.com.