Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Add support for grouping heading with link
Browse files Browse the repository at this point in the history
Related to GH-49.
  • Loading branch information
wooorm committed Mar 23, 2020
1 parent e8a15b8 commit c5b3392
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 5 deletions.
27 changes: 25 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ How to create links (`string`, default: `'prepend'`).
* `'before'` — insert link before the heading
* `'after'` — insert link after the heading

Note that supplying `wrap` will ignore any value defined by the `content`
option.
Supplying `wrap` will ignore any value defined by the `content` option.
Supplying `prepend`, `append`, or `wrap` will ignore the `group` option.

###### `options.content`

Expand All @@ -101,6 +101,8 @@ By default, the following is used:
}
```

If `behavior` is `wrap`, then `content` is ignored.

If `content` is a function, it’s called with the current heading (`Node`) and
should return one or more nodes:

Expand All @@ -118,6 +120,27 @@ function content(node) {
}
```

###### `options.group`

[**hast**][hast] node to wrap the heading and link with (`Function|Node`), if
`behavior` is `before` or `after`.
There is no default.

If `behavior` is `prepend`, `append`, or `wrap`, then `group` is ignored.

If `group` is a function, it’s called with the current heading (`Node`) and
should return a hast node.

```js
const h = require('hastscript')

//

function group(node) {
return h('div.heading-' + node.depth + '-group')
}
```

###### `options.linkProperties`

Extra properties to set on the link (`Object?`).
Expand Down
37 changes: 37 additions & 0 deletions src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,43 @@ test('should accept link properties', (t) => {
)
})

test('should accept a custom group', (t) => {
t.is(
remark()
.use(slug)
.use(html)
.use(headings, {
group: {
tagName: 'div',
properties: {className: ['heading-group']}
},
behaviour: 'before'
})
.processSync('# method')
.toString(),
'<div class="heading-group"><a href="#method"><span class="icon icon-link"></span></a><h1 id="method">method</h1></div>\n'
)
})

test('should accept a custom group as a function', (t) => {
t.is(
remark()
.use(slug)
.use(html)
.use(headings, {group, behaviour: 'after'})
.processSync('# method')
.toString(),
'<div class="heading-1-group"><h1 id="method">method</h1><a href="#method"><span class="icon icon-link"></span></a></div>\n'
)

function group(node) {
return {
tagName: 'div',
properties: {className: ['heading-' + node.depth + '-group']}
}
}
})

test('should do nothing if slugs are not used', (t) => {
t.is(
remark().use(headings).use(html).processSync(base('input.md')).toString(),
Expand Down
34 changes: 31 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const splice = [].splice
let deprecationWarningIssued = false

export default function attacher(options = {}) {
let {linkProperties, behavior, content} = {...defaults, ...options}
let {linkProperties, behavior, content, group} = {...defaults, ...options}
let method

// NOTE: Remove in next major version
Expand Down Expand Up @@ -67,13 +67,19 @@ export default function attacher(options = {}) {

function around(node, url, index, parent) {
const link = create(url)
const grouping = group ? toGrouping(group, node) : undefined

link.data = {
hProperties: toProps(linkProperties),
hChildren: toChildren(content, node)
}

const nodes = behavior === 'before' ? [link, node] : [node, link]
let nodes = behavior === 'before' ? [link, node] : [node, link]

if (grouping) {
grouping.children = nodes
nodes = grouping
}

splice.apply(parent.children, [index, 1].concat(nodes))

Expand All @@ -92,14 +98,36 @@ export default function attacher(options = {}) {
return deepAssign({}, value)
}

function toNode(value, node) {
return typeof value === 'function' ? value(node) : value
}

function toChildren(value, node) {
let children = typeof value === 'function' ? value(node) : value
let children = toNode(value, node)

children = Array.isArray(children) ? children : [children]

return typeof value === 'function' ? children : deepAssign([], children)
}

function toGrouping(value, node) {
const grouping = toNode(value, node)
const hName = grouping.tagName
const hProperties = grouping.properties

return {
type: 'heading-group',
data: {
hName,
hProperties:
typeof value === 'function'
? deepAssign({}, hProperties)
: hProperties
},
children: []
}
}

function create(url, children) {
return {
type: 'link',
Expand Down

0 comments on commit c5b3392

Please sign in to comment.