unified

Project: syntax-tree/mdast-util-heading-range

Package: mdast-util-heading-range@3.1.0

  1. Dependents: 0
  2. mdast utility to use headings as ranges in mdast
  1. markdown 151
  2. util 147
  3. utility 143
  4. unist 133
  5. mdast 88
  6. mdast-util 31
  7. heading 25
  8. range 2

mdast-util-heading-range

Build Coverage Downloads Size Sponsors Backers Chat

mdast utility to find headings and replace the content in their section.

Contents

What is this?

This package is a utility that lets you find a certain heading, then takes the content in their section (from it to the next heading of the same or lower depth), and calls a given handler with the result, so that you can change or replace things.

When should I use this?

This utility is typically useful when you have certain sections that can be generated. For example, this utility is used by remark-toc to update the above Contents heading.

A similar package, mdast-zone, does the same but uses comments to mark the start and end of sections.

Install

This package is ESM only. In Node.js (version 12.20+, 14.14+, or 16.0+), install with npm:

npm install mdast-util-heading-range

In Deno with esm.sh:

import {headingRange} from 'https://esm.sh/mdast-util-heading-range@3'

In browsers with esm.sh:

<script type="module">
  import {headingRange} from 'https://esm.sh/mdast-util-heading-range@3?bundle'
</script>

Use

Say we have the following file, example.md:

# Foo

Bar.

# Baz

…and a module example.js:

import {read} from 'to-vfile'
import {remark} from 'remark'
import {headingRange} from 'mdast-util-heading-range'

const file = await remark()
  .use(myPluginThatReplacesFoo)
  .process(await read('example.md'))

console.log(String(file))

/** @type {import('unified').Plugin<[], import('mdast').Root>} */
function myPluginThatReplacesFoo() {
  return (tree) => {
    headingRange(tree, 'foo', (start, nodes, end) => [
      start,
      {type: 'paragraph', children: [{type: 'text', value: 'Qux.'}]},
      end
    ])
  }
}

…now running node example.js yields:

# Foo

Qux.

# Baz

API

This package exports the identifier headingRange. There is no default export.

headingRange(tree, test|options, handler)

Search tree (Node) and transform a section with handler (Function).

options

Configuration (optional).

options.test

Heading to look for (string, RegExp, Function). When string, wrapped in new RegExp('^(' + value + ')$', 'i'); when RegExp, wrapped in function (value) {expression.test(value)}

options.ignoreFinalDefinitions

Ignore trailing definitions otherwise in the section (boolean, default: false).

function test(value, node)

Function called for each heading with its content (string) and node itself (Heading) to check if it’s the one to look for.

Returns

Whether to use this heading (boolean).

function handler(start, nodes, end, info)

Callback called when a range is found.

Parameters

Arguments.

start

Start of range (Heading).

nodes

Nodes between start and end (Array<Node>).

end

End of range, if any (Node?).

info

Extra info (Object):

Types

This package is fully typed with TypeScript. This package exports the types Handler, Options, TestFunction, Test, and ZoneInfo.

Compatibility

Projects maintained by the unified collective are compatible with all 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.

Security

Improper use of handler can open you up to a cross-site scripting (XSS) attack as the value it returns is injected into the syntax tree. This can become a problem if the tree is later transformed to hast. The following example shows how a script is injected that could run when loaded in a browser.

/** @type {import('mdast-util-heading-range').Handler} */
function handler(start, nodes, end) {
  return [start, {type: 'html', value: '<script>alert(1)</script>'}, end]
}

Yields:

# Foo

<script>alert(1)</script>

# Baz

Either do not use user input in handler or use hast-util-santize.

Contribute

See contributing.md in syntax-tree/.github for ways to get started. See support.md for ways to get help.

This project has a code of conduct. By interacting with this repository, organisation, or community you agree to abide by its terms.

License

MIT © Titus Wormer