mdast-util-heading-range
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
):
parent
(Node
) — parent of the rangestart
(number
) — index ofstart
inparent
end
(number?
) — index ofend
inparent
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
.
Related
mdast-zone
— similar but uses comments to mark the start and end of sections
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.