Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

remark-toc

Package Overview
Dependencies
Maintainers
2
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

remark-toc - npm Package Compare versions

Comparing version 8.0.1 to 9.0.0

lib/index.d.ts

14

index.d.ts

@@ -1,12 +0,2 @@

/**
* Plugin to generate a Table of Contents (TOC).
*
* @type {import('unified').Plugin<[Options?]|void[], Root>}
*/
export default function remarkToc(
options?: void | import('mdast-util-toc/lib').Options | undefined
):
| void
| import('unified').Transformer<import('mdast').Root, import('mdast').Root>
export type Root = import('mdast').Root
export type Options = import('mdast-util-toc').Options
export { default } from "./lib/index.js";
export type Options = import('./lib/index.js').Options;
/**
* @typedef {import('mdast').Root} Root
* @typedef {import('mdast-util-toc').Options} Options
* @typedef {import('./lib/index.js').Options} Options
*/
import {toc} from 'mdast-util-toc'
/**
* Plugin to generate a Table of Contents (TOC).
*
* @type {import('unified').Plugin<[Options?]|void[], Root>}
*/
export default function remarkToc(options = {}) {
return (node) => {
const result = toc(
node,
Object.assign({}, options, {
heading: options.heading || 'toc|table[ -]of[ -]contents?'
})
)
if (
result.endIndex === null ||
result.index === null ||
result.index === -1 ||
!result.map
) {
return
}
node.children = [
...node.children.slice(0, result.index),
result.map,
...node.children.slice(result.endIndex)
]
}
}
export {default} from './lib/index.js'
{
"name": "remark-toc",
"version": "8.0.1",
"description": "remark plugin to generate a Table of Contents (TOC)",
"version": "9.0.0",
"description": "remark plugin to generate a table of contents (TOC)",
"license": "MIT",
"keywords": [
"unified",
"content",
"contents",
"generation",
"markdown",
"mdast",
"plugin",
"remark",
"remark-plugin",
"plugin",
"mdast",
"markdown",
"text",
"plain",
"text",
"table",
"of",
"contents",
"content",
"toc",
"generation"
"unified"
],

@@ -38,5 +34,5 @@ "repository": "remarkjs/remark-toc",

"type": "module",
"main": "index.js",
"types": "index.d.ts",
"exports": "./index.js",
"files": [
"lib/",
"index.d.ts",

@@ -46,41 +42,36 @@ "index.js"

"dependencies": {
"@types/mdast": "^3.0.0",
"mdast-util-toc": "^6.0.0",
"unified": "^10.0.0"
"@types/mdast": "^4.0.0",
"mdast-util-toc": "^7.0.0"
},
"devDependencies": {
"@types/tape": "^4.0.0",
"c8": "^7.0.0",
"@types/node": "^20.0.0",
"c8": "^8.0.0",
"is-hidden": "^2.0.0",
"prettier": "^2.0.0",
"remark": "^14.0.0",
"remark-cli": "^10.0.0",
"prettier": "^3.0.0",
"remark": "^15.0.0",
"remark-cli": "^11.0.0",
"remark-preset-wooorm": "^9.0.0",
"rimraf": "^3.0.0",
"tape": "^5.0.0",
"type-coverage": "^2.0.0",
"typescript": "^4.0.0",
"xo": "^0.45.0"
"typescript": "^5.0.0",
"xo": "^0.56.0"
},
"scripts": {
"build": "rimraf \"test/**/*.d.ts\" \"*.d.ts\" && tsc && type-coverage",
"format": "remark . -qfo --ignore-pattern test/ && prettier . -w --loglevel warn && xo --fix",
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix",
"prepack": "npm run build && npm run format",
"test": "npm run build && npm run format && npm run test-coverage",
"test-api": "node --conditions development test/index.js",
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
"test-coverage": "c8 --100 --reporter lcov npm run test-api"
},
"prettier": {
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": false,
"singleQuote": true,
"bracketSpacing": false,
"semi": false,
"trailingComma": "none"
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"xo": {
"prettier": true
},
"remarkConfig": {
"plugins": [
"preset-wooorm"
"remark-preset-wooorm"
]

@@ -91,5 +82,18 @@ },

"detail": true,
"strict": true,
"ignoreCatch": true
"ignoreCatch": true,
"strict": true
},
"xo": {
"overrides": [
{
"files": [
"test/**/*.js"
],
"rules": {
"no-await-in-loop": "off"
}
}
],
"prettier": true
}
}

@@ -11,3 +11,3 @@ # remark-toc

[**remark**][remark] plugin to generate a table of contents.
**[remark][]** plugin to generate a table of contents.

@@ -22,5 +22,6 @@ ## Contents

* [`unified().use(remarkToc[, options])`](#unifieduseremarktoc-options)
* [`Options`](#options)
* [Examples](#examples)
* [Example: a different heading](#example-a-different-heading)
* [Example: ordered, tight list](#example-ordered-tight-list)
* [Example: ordered, loose list](#example-ordered-loose-list)
* [Example: including and excluding headings](#example-including-and-excluding-headings)

@@ -40,13 +41,6 @@ * [Example: adding a prefix](#example-adding-a-prefix)

**unified** is a project that transforms content with abstract syntax trees
(ASTs).
**remark** adds support for markdown to unified.
**mdast** is the markdown AST that remark uses.
This is a remark plugin that transforms mdast.
## When should I use this?
This project is useful when authors are writing docs in markdown that are
sometimes quite long and hence would benefit from automated overviews inside
them.
sometimes quite long and so would benefit from automated overviews inside them.
It is assumed that headings define the structure of documents and that they can

@@ -69,8 +63,8 @@ be linked to.

You can use the underlying mdast utility [`mdast-util-toc`][mdast-util-toc] and
[create a plugin][create-a-plugin] yourself to do that and more.
[create a plugin][unified-create-a-plugin] yourself to do that and more.
## Install
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]:
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:

@@ -81,13 +75,13 @@ ```sh

In Deno with [Skypack][]:
In Deno with [`esm.sh`][esmsh]:
```js
import remarkToc from 'https://cdn.skypack.dev/remark-toc@8?dts'
import remarkToc from 'https://esm.sh/remark-toc@9'
```
In browsers with [Skypack][]:
In browsers with [`esm.sh`][esmsh]:
```html
<script type="module">
import remarkToc from 'https://cdn.skypack.dev/remark-toc@8?min'
import remarkToc from 'https://esm.sh/remark-toc@9?bundle'
</script>

@@ -98,117 +92,135 @@ ```

Say we have the following file, `example.md`:
Say we have the following file `example.md`:
```markdown
# Alpha
# Pluto
## Table of contents
Pluto is a dwarf planet in the Kuiper belt.
## Bravo
## Contents
### Charlie
## History
## Delta
### Discovery
In the 1840s, Urbain Le Verrier used Newtonian mechanics to predict the
position of…
### Name and symbol
The name Pluto is for the Roman god of the underworld, from a Greek epithet for
Hades…
### Planet X disproved
Once Pluto was found, its faintness and lack of a viewable disc cast doubt…
## Orbit
Pluto’s orbital period is about 248 years…
```
And our module, `example.js`, looks as follows:
…and a module `example.js`:
```js
import {read} from 'to-vfile'
import {remark} from 'remark'
import remarkToc from 'remark-toc'
import {read} from 'to-vfile'
main()
const file = await remark()
.use(remarkToc)
.process(await read('example.md'))
async function main() {
const file = await remark()
.use(remarkToc)
.process(await read('example.md'))
console.log(String(file))
}
console.error(String(file))
```
Now, running `node example` yields:
…then running `node example.js` yields:
```markdown
# Alpha
# Pluto
## Table of contents
Pluto is a dwarf planet in the Kuiper belt.
* [Bravo](#bravo)
## Contents
* [Charlie](#charlie)
* [History](#history)
* [Discovery](#discovery)
* [Name and symbol](#name-and-symbol)
* [Planet X disproved](#planet-x-disproved)
* [Orbit](#orbit)
* [Delta](#delta)
## History
## Bravo
### Discovery
### Charlie
In the 1840s, Urbain Le Verrier used Newtonian mechanics to predict the
position of…
## Delta
```
### Name and symbol
## API
The name Pluto is for the Roman god of the underworld, from a Greek epithet for
Hades…
This package exports no identifiers.
The default export is `remarkToc`.
### Planet X disproved
### `unified().use(remarkToc[, options])`
Once Pluto was found, its faintness and lack of a viewable disc cast doubt…
Generate a table of contents.
Looks for a certain heading, removes everything between it and an equal or
higher heading, and replaces that with a list representing the document
structure, linking to all further headings.
## Orbit
##### `options`
Pluto’s orbital period is about 248 years…
```
Configuration (optional).
## API
##### `options.heading`
This package exports no identifiers.
The default export is [`remarkToc`][api-remark-toc].
Pattern text of heading to look for (`string`, default:
`'toc|table[ -]of[ -]contents?'`).
Wrapped in `new RegExp('^(' + options.heading + ')$', 'i')`, so it’s
case-insensitive and matches the whole heading text.
### `unified().use(remarkToc[, options])`
##### `options.skip`
Generate a table of contents (TOC).
Pattern text of headings to exclude from the generated list (`string`,
optional).
Wrapped in `new RegExp('^(' + options.skip + ')$', 'i')`, so it’s
case-insensitive and matches whole heading texts.
Looks for the first heading matching `options.heading` (case insensitive),
removes everything between it and an equal or higher next heading, and replaces
that with a list representing the rest of the document structure, linking to
all further headings.
###### `options.maxDepth`
###### Parameters
Maximum heading depth to include in the generated list (`number?`, default:
`6`).
This is inclusive: when set to `3`, headings with a rank of 3 are included
(those with three hashes: `###`).
* `options` ([`Options`][api-options], optional)
— configuration
###### `options.tight`
###### Returns
Whether to compile list items tightly (`boolean?`, default: `false`).
The default is to add space around items.
Transform ([`Transformer`][unified-transformer]).
###### `options.ordered`
### `Options`
Whether to compile list items as an ordered list (`boolean?`, default: `false`).
The default is to use an unordered list.
Configuration (TypeScript type).
###### `options.prefix`
###### Fields
String to prepend before links to headings (`string?`, default: `null`, example:
`'user-content-'`).
This is useful when combining remark with [rehype][] through
[`remark-rehype`][remark-rehype] after this plugin, and using
[`rehype-sanitize`][rehype-sanitize] to prevent DOM clobbering of user generated
markdown.
* `heading` (`string`, default: `'(table[ -]of[ -])?contents?|toc'`)
— heading to look for, wrapped in `new RegExp('^(' + value + ')$', 'i')`
* `maxDepth` (`number`, default: `6`)
— max heading depth to include in the table of contents; this is inclusive:
when set to `3`, level three headings are included (those with three hashes,
`###`)
* `skip` (`string`, optional)
— headings to skip, wrapped in `new RegExp('^(' + value + ')$', 'i')`;
any heading matching this expression will not be present in the table of
contents
* `parents` ([`Test` from `unist-util-is`][unist-util-is-test], default:
`tree`)
— allow headings to be children of certain node types
* `tight` (`boolean`, default: `true`)
— whether to compile list items tightly, otherwise space is added around
items
* `ordered` (`boolean`, default: `false`)
— whether to compile list items as an ordered list, otherwise they are
unordered
* `prefix` (`string`, optional, example: `'user-content-'`)
— add a prefix to links to headings in the table of contents;
useful for example when later going from markdown to HTML and sanitizing
with [`rehype-sanitize`][rehype-sanitize]
###### `options.parents`
Parents (such as block quotes and lists) of headings to include in the generated
list ([`is`-compatible][is] test, default: the root node).
By default only top level headings are used.
Pass `['root', 'blockquote']` to also link to headings in block quotes.
## Examples

@@ -222,18 +234,18 @@

```diff
@@ -6,7 +6,7 @@ main()
@@ -3,7 +3,7 @@ import remarkToc from 'remark-toc'
import {read} from 'to-vfile'
async function main() {
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {heading: 'contents'})
.process(await read('example.md'))
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {heading: 'structure'})
.process(await read('example.md'))
console.log(String(file))
console.error(String(file))
```
…that would search for `Contents` (case-insensitive) headings.
…that would search for `structure` (case-insensitive) headings.
### Example: ordered, tight list
### Example: ordered, loose list
The options `ordered` and `tight` can be turned on to change the list.
The options `ordered` and `tight` can be toggled to change the list.
The example from before can be changed to generate a tight, ordered list like

@@ -243,11 +255,11 @@ so:

```diff
@@ -6,7 +6,10 @@ main()
@@ -3,7 +3,7 @@ import remarkToc from 'remark-toc'
import {read} from 'to-vfile'
async function main() {
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {tight: true, ordered: true})
.process(await read('example.md'))
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {ordered: true, tight: false})
.process(await read('example.md'))
console.log(String(file))
console.error(String(file))
```

@@ -258,5 +270,9 @@

```markdown
1. [Bravo](#bravo)
1. [Charlie](#charlie)
2. [Delta](#delta)
1. [History](#history)
1. [Discovery](#discovery)
2. [Name and symbol](#name-and-symbol)
3. [Planet X disproved](#planet-x-disproved)
2. [Orbit](#orbit)
```

@@ -266,37 +282,35 @@

The options `maxDepth`, `skip`, and `parents` can be used to include and exclude
certain headings from list.
The example from before can be changed to generate a tight, ordered list like
so:
The options `maxDepth`, `parents`, and `skip` can be used to include and
exclude certain headings from list.
The example from before can be changed to only include level 1, 2, and 3
headings, to include headings directly in list items, and to exclude headings
with the text `delta` (case-insensitive, full match):
```diff
@@ -6,7 +6,10 @@ main()
@@ -3,7 +3,7 @@ import remarkToc from 'remark-toc'
import {read} from 'to-vfile'
async function main() {
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {maxDepth: 3, skip: 'delta', parents: ['root', 'listItem']})
.process(await read('example.md'))
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {maxDepth: 3, parents: ['listItem', 'root'], skip: 'delta'})
.process(await read('example.md'))
console.log(String(file))
console.error(String(file))
```
…that would exclude level 4, 5, and 6 headings, exclude headings of `delta`
(case-insensitive, full match), and include headings directly in a list item.
### Example: adding a prefix
The option `prefix` can set to prepend a string to all links to headings in the
The `prefix` option can set to prepend a string to all links to headings in the
generated list:
```diff
@@ -6,7 +6,10 @@ main()
@@ -3,7 +3,7 @@ import remarkToc from 'remark-toc'
import {read} from 'to-vfile'
async function main() {
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {prefix: 'user-content-'})
.process(await read('example.md'))
const file = await remark()
- .use(remarkToc)
+ .use(remarkToc, {prefix: 'user-content-'})
.process(await read('example.md'))
console.log(String(file))
console.error(String(file))
```

@@ -307,7 +321,7 @@

```markdown
* [Bravo](#user-content-bravo)
* [Charlie](#user-content-charlie)
* [Delta](#user-content-delta)
* [History](#user-content-history)
* [Discovery](#user-content-discovery)
* [Name and symbol](#user-content-name-and-symbol)
* [Planet X disproved](#user-content-planet-x-disproved)
* [Orbit](#user-content-orbit)
```

@@ -318,12 +332,14 @@

This package is fully typed with [TypeScript][].
It exports an `Options` type, which specifies the interface of the accepted
options.
It exports the additional type [`Options`][api-options].
## Compatibility
Projects maintained by the unified collective are compatible with all maintained
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
As of now, that is Node.js 12.20+, 14.14+, and 16.0+.
Our projects sometimes work with older versions, but this is not guaranteed.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, `remark-toc@^9`, compatible
with Node.js 16.
This plugin works with `unified` version 3+ and `remark` version 4+.

@@ -334,3 +350,3 @@

Use of `remark-toc` involves user content and changes the tree, so it can open
you up for a [cross-site scripting (XSS)][xss] attack.
you up for a [cross-site scripting (XSS)][wiki-xss] attack.

@@ -344,3 +360,3 @@ Existing nodes are copied into the table of contents.

```markdown
# Table of Contents
# Contents

@@ -355,3 +371,3 @@ ## Bravo<script>alert(1)</script>

```markdown
# Table of Contents
# Contents

@@ -367,3 +383,3 @@ - [Bravo<script>alert(1)</script>](#bravoscriptalert1script)

This may become a problem if the markdown is later transformed to
[**rehype**][rehype] ([**hast**][hast]) or opened in an unsafe markdown viewer.
**[rehype][]** (**[hast][]**) or opened in an unsafe markdown viewer.

@@ -414,5 +430,5 @@ ## Related

[size-badge]: https://img.shields.io/bundlephobia/minzip/remark-toc.svg
[size-badge]: https://img.shields.io/bundlejs/size/remark-toc
[size]: https://bundlephobia.com/result?p=remark-toc
[size]: https://bundlejs.com/?q=remark-toc

@@ -431,11 +447,13 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg

[skypack]: https://www.skypack.dev
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[esmsh]: https://esm.sh
[health]: https://github.com/remarkjs/.github
[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md
[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
[support]: https://github.com/remarkjs/.github/blob/main/support.md
[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md

@@ -446,26 +464,32 @@ [license]: license

[remark]: https://github.com/remarkjs/remark
[hast]: https://github.com/syntax-tree/hast
[unified]: https://github.com/unifiedjs/unified
[mdast-util-toc]: https://github.com/syntax-tree/mdast-util-toc
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[rehype]: https://github.com/rehypejs/rehype
[typescript]: https://www.typescriptlang.org
[rehype-autolink-headings]: https://github.com/rehypejs/rehype-autolink-headings
[rehype]: https://github.com/rehypejs/rehype
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
[hast]: https://github.com/syntax-tree/hast
[rehype-slug]: https://github.com/rehypejs/rehype-slug
[remark]: https://github.com/remarkjs/remark
[remark-rehype]: https://github.com/remarkjs/remark-rehype
[rehype-slug]: https://github.com/rehypejs/rehype-slug
[typescript]: https://www.typescriptlang.org
[rehype-autolink-headings]: https://github.com/rehypejs/rehype-autolink-headings
[unified]: https://github.com/unifiedjs/unified
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
[unified-transformer]: https://github.com/unifiedjs/unified#transformer
[mdast-util-toc]: https://github.com/syntax-tree/mdast-util-toc
[unified-create-a-plugin]: https://unifiedjs.com/learn/guide/create-a-plugin/
[create-a-plugin]: https://unifiedjs.com/learn/guide/create-a-plugin/
[unist-util-is-test]: https://github.com/syntax-tree/unist-util-is#test
[is]: https://github.com/syntax-tree/unist-util-is#api
[wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[api-options]: #options
[api-remark-toc]: #unifieduseremarktoc-options
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc