Skip to content

Commit

Permalink
0.6.0 Rewrite of TOC generator
Browse files Browse the repository at this point in the history
The TOC generator was rewritten, because the old *on-the-fly* generator couldn't deal with unexpected order of headings and double-indentations. It is now a three-step process:

1. Gather all headings in a list.
2. Turn that list into a nested tree.
3. Generate HTML code based on the nested tree.

Although all tests pass, this release could introduce some **breaking changes** for you, if you relied on the old way of doing things. Check the test cases to get a better understanding how this plugin handles various cases.

* **Added**: Support for `markdown-it-attrs` (fixes #54)
* **Changed**: Respects unexpected nesting order (fixes #55)
* **Changed**: Uses anchor targets from existing id attributes (for example, set by `markdown-it-attrs` or `markdown-it-anchor`)
* **Changed**: Now nests list correctly if there is a jump (for example: h2, h2, h4 -> h4 is now double-indented)
* **Removed**: unused tests
  • Loading branch information
Chris Maas committed Nov 12, 2021
1 parent 7851a62 commit 62bfc75
Show file tree
Hide file tree
Showing 18 changed files with 881 additions and 119 deletions.
25 changes: 25 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,25 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]


## [0.6.0] - 2021-11-12

The TOC generator was rewritten, because the old *on-the-fly* generator couldn't deal with unexpected order of headings and double-indentations. It is now a three-step process:

1. Gather all headings in a list.
2. Turn that list into a nested tree.
3. Generate HTML code based on the nested tree.

Although all tests pass, this release could introduce some **breaking changes** for you, if you relied on the old way of doing things. Check the test cases to get a better understanding how this plugin handles various cases.

* **Added**: Support for `markdown-it-attrs` (fixes #54)
* **Changed**: Respects unexpected nesting order (fixes #55)
* **Changed**: Uses anchor targets from existing id attributes (for example, set by `markdown-it-attrs` or `markdown-it-anchor`)
* **Changed**: Now nests list correctly if there is a jump (for example: h2, h2, h4 -> h4 is now double-indented)
* **Removed**: unused tests
112 changes: 108 additions & 4 deletions README.md
@@ -1,16 +1,13 @@
# markdown-it-table-of-contents
A table of contents plugin for Markdown-it. Simple, customizable and with a default slugifier that matches that of https://www.npmjs.com/package/markdown-it-anchor (>5.0.0).

## Looking for maintainer
I'm looking for someone to take over this package to maintain and improve on it. Interested? Open an issue and just quickly explain your thoughts...

## Usage

``` javascript
var MarkdownIt = require("markdown-it");
var md = new MarkdownIt();

md.use(require("markdown-it-anchor").default); // Optional, but makes sense as you really want to link to something
md.use(require("markdown-it-anchor").default); // Optional, but makes sense as you really want to link to something, see info about recommended plugins below
md.use(require("markdown-it-table-of-contents"));
```

Expand Down Expand Up @@ -95,3 +92,110 @@ function transformLink(link) {
return transformedLink;
}
```

## Recommended plugins

By default, markdown-it-table-of-contents collects all headings and renders a nested list. It uses the `slugify()` function to create anchor targets for the links in the list. However, the headlines in your markdown document are not touched by markdown-it-table-of-contents. You'd have a nice table of contents, but the links don't link to anything. That's why you need another plugin to generate ids (anchor link targets) for all of your headlines. There are two recommended plugins to achieve this:

### [markdown-it-anchor](https://www.npmjs.com/package/markdown-it-anchor)

This plugin transforms all headlines in a markdown document so that the HTML code includes an id. It *slugifies* the headline:

```markdown
## Hello world, I think you should read this article
```

Becomes

```html
<h2 id="hello-world-i-think-you-should-read-this-article">Hello world</h2>
```

### [markdown-it-attrs](https://www.npmjs.com/package/markdown-it-attrs)

This plugin lets you attach custom attributes to your headlines. This is especially useful, if you have long headlines but want short anchors:

```markdown
## Hello world, I think you should read this article {#hello}
```

Becomes

```html
<h2 id="hello">Hello world, I think you should read this article</h2>
```

## Full example with unusual headline order

Of course, both plugins can be combined. markdown-it-anchor ignores headlines that already have an id attribute.

Furthermore, markdown-it-table-of-contents can handle unusual heading orders. Consider the full example below:

```js
var md = new MarkdownIt();
md.use(markdownItTOC, {
"includeLevel": [2,3,4]
});
md.use(require("markdown-it-attrs"));
md.use(require("markdown-it-anchor"));
```


```markdown
# Article

[[toc]]

### A message from our sponsors

Ad

## Hello world, I think you should read this article {#hello}

Lorem ipsum

## What's next?

Read this next...

#### See related articles {#related}
```

HTML output:

```html
<h1 id="article">Article</h1>
<p>
<div class="table-of-contents">
<ul>
<li>
<ul>
<li><a href="#a-message-from-our-sponsors">A message from our sponsors</a></li>
</ul>
</li>
<li><a href="#hello">Hello world, I think you should read this article</a></li>
<li><a href="#what's-next%3F">What's next?</a>
<ul>
<li>
<ul>
<li><a href="#related">See related articles</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</p>
<h3 id="a-message-from-our-sponsors">A message from our sponsors</h3>
<p>Ad</p>
<h2 id="hello">Hello world, I think you should read this article</h2>
<p>Lorem ipsum</p>
<h2 id="what's-next%3F">What's next?</h2>
<p>Read this next...</p>
<h4 id="related">See related articles</h4>
```

## Additional infos

* This plugin outputs a semantically correct table of contents. Sub-lists are rendered within the parent `<li>` tag and not as a separate (empty) `<li>`.
* Headlines can be in an arbitrary order. For example, h3, h2, h4. Please note that the jump from h2 to h4 causes a doube-indentation, which is correct.

0 comments on commit 62bfc75

Please sign in to comment.