loading...
Cover image for Generate Table of Contents with GitHub Actions

Generate Table of Contents with GitHub Actions

fredericlemay profile image Frederic Lemay Updated on ・4 min read

I love taking notes in Markdown and lately, I've been using GitHub to write (and store) them.

There are many advantages of using GitHub: accessible on different platforms, online, offline, Markdown support, editor agnostic, versioning, simple structure (files/folders), and free.

However, one thing that is not supported out of the box is generating Table of Contents (TOC). With it, I can organize my notes differently and have many of them into a single Markdown file.

Here is how I generate the Table of Contents for my notes using GitHub Actions.

Prerequisites

  • Make
  • Docker
  • Compose
  • GitHub account
  • Git
  • Terminal

Implementation

My notes repository contains many files and folders but for the purpose of this blog post, I will keep everything as simple as possible. Below is the file structure of an example git repository.

$ tree -a
.
├── .git
│   ├── ...
├── Makefile
├── docker-compose.yml
├── story.md
└── package.json

The repository has one note written in Markdown called story.md which has some random content.

# Story

## Introduction

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Praesent elementum tincidunt felis, condimentum accumsan nibh imperdiet nec.
Sed cursus justo eu purus rhoncus, id facilisis lorem semper.

## Development

Duis nunc arcu, bibendum quis turpis ut, dapibus feugiat massa.
Sed tempus tortor eget diam porta vulputate. Ut tempor iaculis suscipit.
Morbi scelerisque felis ac justo consectetur luctus.

## Conclusion

Nullam malesuada rutrum gravida. Vivamus sit amet fermentum odio.
Donec tincidunt ex odio, vitae convallis ante posuere nec.

Since generating the Table of Contents is not a default option, I searched for a generator and found DocToc, a NodeJS module.

DocToc: Generates table of contents for markdown files inside local git repository. Links are compatible with anchors generated by github or other sites.

To use DocToc, I created package.json file and added the module as a development dependency.

{
  "name": "mynotes",
  "devDependencies": {
    "doctoc": "^1.4.0"
  }
}

I often use Docker to ensure consistency between different platforms like, in this case, my laptop and GitHub. In the docker-compose.yml file, I defined a service named node which will be used to install DocToc and generate the TOC using the latest NodeJS Docker image.

version: '3.7'
services:
  node:
    image: node
    volumes:
      - type: bind
        source: "."
        target: /opt/app
    working_dir: /opt/app

The last file is Makefile which encapsulates the Docker Compose commands. The deps target downloads the NodeJS Docker image and installs DocToc. The generateTOC target generates the Table of Contents with DocToc inside a NodeJS Docker container.

deps:
    docker-compose pull node
    docker-compose run --rm node yarn install

generateTOC:
    docker-compose run --rm node yarn doctoc .

Finally, to include the TOC to my notes, I simply run make deps generateTOC in a terminal. The story.md file is now updated.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [Story](#story)
    - [Introduction](#introduction)
    - [Development](#development)
    - [Conclusion](#conclusion)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# Story

## Introduction

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Praesent elementum tincidunt felis, condimentum accumsan nibh imperdiet nec.
Sed cursus justo eu purus rhoncus, id facilisis lorem semper.

## Development

Duis nunc arcu, bibendum quis turpis ut, dapibus feugiat massa.
Sed tempus tortor eget diam porta vulputate. Ut tempor iaculis suscipit.
Morbi scelerisque felis ac justo consectetur luctus.

## Conclusion

Nullam malesuada rutrum gravida. Vivamus sit amet fermentum odio.
Donec tincidunt ex odio, vitae convallis ante posuere nec.

Et voilà! I then commit my changes to master, push, and view them on GitHub.

This works well on a computer where tools like Make, Docker, and Compose are installed. I could even go furter and automate the process with Git Hooks.

However, what if I write on a tablet or directly on GitHub website? The Table of Contents will likely get out of date. Wouldn't be great to get it generated no matter where the notes are written from? GitHub Actions to the rescue!

GitHub Actions

GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.

Below is the structure of the example git repository with GitHub Actions included.

$ tree -a
.
├── .git
│   ├── ...
├── .github
│   └── workflows
│       └── generate_toc.yml
├── Makefile
├── docker-compose.yml
├── story.md
└── package.json

I defined a workflow in the .github/workflows/generate_toc.yml file to generate the Table of Contents whenever I push to master branch.

name: Generate TOC
on:
  push:
    branches:
      - master
jobs:
  generateTOC:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Generate TOC
      run: make deps generateTOC
    - name: Auto commit
      uses: stefanzweifel/git-auto-commit-action@v2.1.0
      with:
        commit_message: Apply automatic changes - TOC generated
        branch: master
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

This workflow checks out the repository on a master branch push event, runs the command make deps generateTOC to generate the Table of Contents, and finally, commits the changes automatically to master with the GitHub Action named git-auto-commit-action.

From the GitHub repository, I can see my Generate TOC workflow being executed.

GitHhub Workflows

And see the automated commit with the Table of Contents updated from the workflow right after I updated my notes.

GitHub Commits

Wrapping Up

I am more than happy that GitHub Actions supports Make, Docker, and Compose. I could develop and test locally some parts of my workflow, and feel confident that they will work on GitHub. And now, I can write my notes from anywhere and get the Table of Contents magically updated. This is a simple use case but there are many Actions that can just be "plug & play" to create more sophisticated workflows.


Liked this blog post? Checkout 3musketeers.io to learn more about how to build, test, and deploy your apps from anywhere, the same way!

Disclaimer: Do your own research before using this solution and do not store sensitive information in plain text on GitHub.

Discussion

pic
Editor guide