Skip to content

Commit

Permalink
Add support for headingProperties
Browse files Browse the repository at this point in the history
Closes GH-20.
Closes GH-21.

Co-authored-by: Chris Weber <chris963@gmail.com>
  • Loading branch information
wooorm and chrisweb committed Nov 8, 2023
1 parent 31159c0 commit 01133a3
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 34 deletions.
22 changes: 13 additions & 9 deletions lib/index.js
Expand Up @@ -37,6 +37,8 @@
* @property {Readonly<ElementContent> | ReadonlyArray<ElementContent> | Build | null | undefined} [group]
* Content to wrap the heading and link with, if `behavior` is `'after'` or
* `'before'` (optional).
* @property {Readonly<Properties> | BuildProperties | null | undefined} [headingProperties]
* Extra properties to set on the heading (optional).
* @property {Readonly<Properties> | BuildProperties | null | undefined} [properties]
* Extra properties to set on the link when injecting (default:
* `{ariaHidden: true, tabIndex: -1}` if `'append'` or `'prepend'`, otherwise
Expand Down Expand Up @@ -97,7 +99,8 @@ const emptyOptions = {}
*/
export default function rehypeAutolinkHeadings(options) {
const settings = options || emptyOptions
let props = settings.properties
let properties = settings.properties
const headingOroperties = settings.headingProperties
const behavior = settings.behavior || 'prepend'
const content = settings.content
const group = settings.group
Expand All @@ -113,8 +116,8 @@ export default function rehypeAutolinkHeadings(options) {
} else {
method = inject

if (!props) {
props = {ariaHidden: 'true', tabIndex: -1}
if (!properties) {
properties = {ariaHidden: 'true', tabIndex: -1}
}
}

Expand All @@ -129,6 +132,7 @@ export default function rehypeAutolinkHeadings(options) {
return function (tree) {
visit(tree, 'element', function (node, index, parent) {
if (headingRank(node) && node.properties.id && is(node, index, parent)) {
Object.assign(node.properties, toProperties(headingOroperties, node))
return method(node, index, parent)
}
})
Expand All @@ -138,7 +142,7 @@ export default function rehypeAutolinkHeadings(options) {
function inject(node) {
const children = toChildren(content || contentDefaults, node)
node.children[behavior === 'prepend' ? 'unshift' : 'push'](
create(node, toProperties(props, node), children)
create(node, toProperties(properties, node), children)
)

return [SKIP]
Expand All @@ -150,7 +154,7 @@ export default function rehypeAutolinkHeadings(options) {
if (typeof index !== 'number' || !parent) return

const children = toChildren(content || contentDefaults, node)
const link = create(node, toProperties(props, node), children)
const link = create(node, toProperties(properties, node), children)
let nodes = behavior === 'before' ? [link, node] : [node, link]

if (group) {
Expand Down Expand Up @@ -184,7 +188,7 @@ export default function rehypeAutolinkHeadings(options) {
node.children = [
create(
node,
toProperties(props, node),
toProperties(properties, node),
Array.isArray(after) ? [...before, ...after] : [...before, after]
)
]
Expand Down Expand Up @@ -213,18 +217,18 @@ function clone(thing) {
*
* @param {Readonly<Element>} node
* Related heading.
* @param {Properties | undefined} props
* @param {Properties | undefined} properties
* Properties to set on the link.
* @param {Array<ElementContent>} children
* Content.
* @returns {Element}
* Link.
*/
function create(node, props, children) {
function create(node, properties, children) {
return {
type: 'element',
tagName: 'a',
properties: {...props, href: '#' + node.properties.id},
properties: {...properties, href: '#' + node.properties.id},
children
}
}
Expand Down
3 changes: 3 additions & 0 deletions readme.md
Expand Up @@ -217,6 +217,9 @@ Configuration (TypeScript type).
optional)
— content to wrap the heading and link with, if `behavior` is `'after'` or
`'before'`
* `headingProperties` ([`BuildProperties`][api-build-properties] or
[`Properties`][hast-properties], optional)
— extra properties to set on the heading
* `properties` ([`BuildProperties`][api-build-properties] or
[`Properties`][hast-properties], default:
`{ariaHidden: true, tabIndex: -1}` if `'append'` or `'prepend'`, otherwise
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/heading-properties/config.json
@@ -0,0 +1,6 @@
{
"headingProperties": {
"className": ["foo", "bar", "baz"],
"dataQux": "quux"
}
}
1 change: 1 addition & 0 deletions test/fixtures/heading-properties/input.html
@@ -0,0 +1 @@
<h1 id="foo">Bar</h1>
1 change: 1 addition & 0 deletions test/fixtures/heading-properties/output.html
@@ -0,0 +1 @@
<h1 id="foo" class="foo bar baz" data-qux="quux"><a aria-hidden="true" tabindex="-1" href="#foo"><span class="icon icon-link"></span></a>Bar</h1>
28 changes: 3 additions & 25 deletions test/index.js
Expand Up @@ -30,31 +30,9 @@ test('rehypeAutolinkHeadings', async function (t) {
assert.equal(node.properties.id, 'a')
return {type: 'element', tagName: 'div', properties: {}, children: []}
},
properties(node) {
headingProperties(node) {
assert.equal(node.properties.id, 'a')
return {dataX: 'y'}
}
})
.process('<h1 id=a>b</h1>')

assert.deepEqual(
String(file),
'<div><h1 id="a">b</h1><a data-x="y" href="#a"><i></i></a></div>'
)
})

await t.test('should support functions', async function () {
const file = await rehype()
.data('settings', {fragment: true})
.use(rehypeAutolinkHeadings, {
behavior: 'after',
content(node) {
assert.equal(node.properties.id, 'a')
return {type: 'element', tagName: 'i', properties: {}, children: []}
},
group(node) {
assert.equal(node.properties.id, 'a')
return {type: 'element', tagName: 'div', properties: {}, children: []}
return {dataA: 'b'}
},
properties(node) {
assert.equal(node.properties.id, 'a')
Expand All @@ -65,7 +43,7 @@ test('rehypeAutolinkHeadings', async function (t) {

assert.deepEqual(
String(file),
'<div><h1 id="a">b</h1><a data-x="y" href="#a"><i></i></a></div>'
'<div><h1 id="a" data-a="b">b</h1><a data-x="y" href="#a"><i></i></a></div>'
)
})

Expand Down

0 comments on commit 01133a3

Please sign in to comment.