Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/abhinav/goldmark-toc

Support for generating Tables of Contents from goldmark Markdown documents.
https://github.com/abhinav/goldmark-toc

golang markdown

Last synced: 15 days ago
JSON representation

Support for generating Tables of Contents from goldmark Markdown documents.

Awesome Lists containing this project

README

        

# goldmark-toc

[![Go Reference](https://pkg.go.dev/badge/go.abhg.dev/goldmark/toc.svg)](https://pkg.go.dev/go.abhg.dev/goldmark/toc)
[![CI](https://github.com/abhinav/goldmark-toc/actions/workflows/ci.yml/badge.svg)](https://github.com/abhinav/goldmark-toc/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/abhinav/goldmark-toc/branch/main/graph/badge.svg?token=OLXTVHEIOG)](https://codecov.io/gh/abhinav/goldmark-toc)

goldmark-toc is an add-on for the [goldmark] Markdown parser that adds support
for rendering a table-of-contents.

[goldmark]: http://github.com/yuin/goldmark

**Demo**:
A web-based demonstration of the extension is available at
.

## Installation

```bash
go get go.abhg.dev/goldmark/toc@latest
```

## Usage

To use goldmark-toc, import the `toc` package.

```go
import "go.abhg.dev/goldmark/toc"
```

Following that, you have three options for using this package:

- [Extension][]: This is the easiest way to get a table of contents into your
document and provides very little control over the output.
- [Transformer][]: This is the next easiest option and provides more control
over the output.
- [Manual][]: This option requires the most work but also provides the most
control.

[Extension]: #extension
[Transformer]: #transformer
[Manual]: #manual

### Extension

To use this package as a simple Goldmark extension, install the `Extender`
when constructing the `goldmark.Markdown` object.

```go
markdown := goldmark.New(
// ...
goldmark.WithParserOptions(parser.WithAutoHeadingID()),
goldmark.WithExtensions(
// ...
&toc.Extender{},
),
)
```

This will add a "Table of Contents" section to the top of every Markdown
document parsed by this Markdown object.

> NOTE: The example above enables `parser.WithAutoHeadingID`. Without this or
> a custom implementation of `parser.IDs`, none of the headings in the
> document will have links generated for them.

#### Changing the title

If you want to use a title other than "Table of Contents",
set the `Title` field of `Extender`.

```go
&toc.Extender{
Title: "Contents",
}
```

You can specify an ID for the title heading with the `TitleID` option.

```go
&toc.Extender{
Title: "Contents",
TitleID: "toc-header",
}
```

#### Adding an ID

If you want the rendered HTML list to include an id,
set the `ListID` field of `Extender`.

```go
&toc.Extender{
ListID: "toc",
}
```

This will render:

```html




```

#### Limiting the Table of Contents

By default, goldmark-toc will include all headers in the table of contents.
If you want to limit the depth of the table of contents,
use the `MinDepth` and `MaxDepth` field.

```go
&toc.Extender{
MinDepth: 2,
MaxDepth: 3,
}
```

Headers with a level lower or higher than the specified values
will not be included in the table of contents.

#### Compacting the Table of Contents

The Table of Contents generated by goldmark-toc matches your heading hierarchy
exactly.
This can be a problem if you have multiple levels of difference between items.
For example, if you have the document:

```markdown
# h1
### h3
```

goldmark-toc will generate a TOC with the equivalent of the following,
resulting in an empty entry between h1 and h3.

```markdown
- h1
-
- h3
```

You can use the `Compact` option to collapse away these intermediate items.

```go
&toc.Extender{
Compact: true,
}
```

With this option enabled, the hierarchy above
will render as the equivalent of the following.

```markdown
- h1
- h3
```

### Transformer

Installing this package as an AST Transformer provides slightly more control
over the output.
To use it, install the AST transformer on the Goldmark Markdown parser.

```go
markdown := goldmark.New(...)
markdown.Parser().AddOptions(
parser.WithAutoHeadingID(),
parser.WithASTTransformers(
util.Prioritized(&toc.Transformer{
Title: "Contents",
}, 100),
),
)
```

This will generate a "Contents" section at the top of all Markdown documents
parsed by this parser.

As with the previous example, this enables `parser.WithAutoHeadingID` to get
auto-generated heading IDs.

### Manual

If you use this package manually to generate Tables of Contents, you have a
lot more control over the behavior. This requires a few steps.

#### Parse Markdown

Parse a Markdown document with goldmark.

```go
markdown := goldmark.New(...)
markdown.Parser().AddOptions(parser.WithAutoHeadingID())
doc := markdown.Parser().Parse(text.NewReader(src))
```

Note that the parser must be configured to generate IDs for headers or the
headers in the table of contents won't have anything to point to. This can be
accomplished by adding the `parser.WithAutoHeadingID` option as in the example
above, or with a custom implementation of [`goldmark/parser.IDs`] by using the
snippet below.

[`goldmark/parser.IDs`]: https://pkg.go.dev/github.com/yuin/goldmark/parser#IDs

```go
markdown := goldmark.New(...)
pctx := parser.NewContext(parser.WithIDs(ids))
doc := parser.Parse(text.NewReader(src), parser.WithContext(pctx))
```

#### Build a table of contents

After parsing a Markdown document, inspect it with `toc`.

```go
tree, err := toc.Inspect(doc, src)
if err != nil {
// handle the error
}
```

If you need to limit the depth of the table of contents,
use the `MinDepth` and `MaxDepth` option.

```go
tree, err := toc.Inspect(doc, src, toc.MinDepth(2), toc.MaxDepth(3))
```

#### Generate a Markdown list

You can render the table of contents into a Markdown list with
`toc.RenderList`.

```go
list := toc.RenderList(tree)
```

This builds a list representation of the table of contents to be rendered as
Markdown or HTML.

You may manipulate the `tree` before rendering the list.

#### Render HTML

Finally, render this table of contents along with your Markdown document:

```go
// Render the table of contents.
if list != nil {
// list will be nil if the table of contents is empty
// because there were no headings in the document.
markdown.Renderer().Render(output, src, list)
}

// Render the document.
markdown.Renderer().Render(output, src, doc)
```

Alternatively, include the table of contents into your Markdown document in
your desired position and render it using your Markdown renderer.

```go
// Prepend table of contents to the front of the document.
if list != nil {
doc.InsertBefore(doc, doc.FirstChild(), list)
}

// Render the document.
markdown.Renderer().Render(output, src, doc)
```

##### Customize TOC attributes

If you want the rendered TOC to have an id or other attributes,
use [Node.SetAttribute](https://pkg.go.dev/github.com/yuin/goldmark/ast#Node.SetAttribute)
on the `ast.Node` returned by `toc.RenderList`.

For example, with the following:

```go
list := toc.RenderList(tree)
list.SetAttribute([]byte("id"), []byte("toc"))
```

The output will take the form:

```html




```