Skip to content

Commit

Permalink
feat: adding option to disable default, reorganizing code, more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Flynn committed Aug 17, 2023
1 parent 86a55d3 commit 7b1d28d
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 24 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@
<h3 id="my-great-heading">My Great Heading</h3>
```

### API

This package exports no identifiers. The default export is `remarkHeaderId`.

`unified().use(remarkHeadingId[, options])`

#### options

Configuration (optional).

#### options.defaults

Whether to add default titles based on the title text (boolean, default: true).

## Contributing

- Fork it!
Expand Down
34 changes: 33 additions & 1 deletion __tests__/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const remark = require('remark')
const stringify = require('remark-rehype')
const html = require('rehype-stringify')
const remarkHeadingId = require('../')
const { formatDefaultId } = require('../util')

describe('remarkHeadingId', function() {
it('should parse well', function() {
it('custom header', function() {
let { contents } = remark()
.data('settings', {
position: false
Expand All @@ -29,6 +30,37 @@ describe('remarkHeadingId', function() {
`)
})

it('default header values', function() {
const values = new Map()
values
.set('title', 'title')
.set('multiple words', 'multiple-words')
.set('Multiple Words With Case', 'multiple-words-with-case')
.set('extra spaces ', 'extra-spaces')
.set('special (characters) *_-+=[]{}<>,./?&^%$#@!`~ ', 'special-characters')
.forEach((value, key) => expect(formatDefaultId(key)).toBe(value))
})

it('defaults option can disable defaults', function() {
let { contents } = remark()
.data('settings', {
position: false
})
.use(remarkHeadingId, { defaults: false })
.use(stringify)
.use(html).processSync(`# head
# cus head1 {#idd-id}
# cus head2 {#idd id}
# cus head3 {#中文 id}`)

expect(contents).toMatchInlineSnapshot(`
"<h1>head</h1>
<h1 id=\\"idd-id\\">cus head1</h1>
<h1 id=\\"idd id\\">cus head2</h1>
<h1 id=\\"中文 id\\">cus head3</h1>"
`)
})

it('should parse well which contains inline syntax', function() {
let { contents } = remark()
.data('settings', {
Expand Down
30 changes: 7 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,11 @@
*/

const visit = require('unist-util-visit')
const _ = require('lodash')
const { setNodeId, getDefaultId } = require('./util')

const extractText = children => {
return children
.map(child => {
if (!_.isEmpty(child.value)) {
return child.value
} else if (child.children && child.children.length > 0) {
return extractText(child.children)
} else {
return ''
}
})
.join(' ')
}

module.exports = function() {
module.exports = function(options = { defaults: true }) {
return function(node) {
visit(node, 'heading', node => {
if (!node.data) node.data = {}
if (!node.data.hProperties) node.data.hProperties = {}

let lastChild = node.children[node.children.length - 1]
if (lastChild && lastChild.type === 'text') {
let string = lastChild.value.replace(/ +$/, '')
Expand All @@ -34,7 +17,7 @@ module.exports = function() {
if (matched) {
let id = matched[1]
if (!!id.length) {
node.data.id = node.data.hProperties.id = id
setNodeId(node, id)

string = string.substring(0, matched.index)
lastChild.value = string
Expand All @@ -43,9 +26,10 @@ module.exports = function() {
}
}

// If no custom id was found, use default instead
let fullText = extractText(node.children)
node.data.id = node.data.hProperties.id = _.kebabCase(fullText)
if (options.defaults) {
// If no custom id was found, use default instead
setNodeId(node, getDefaultId(node.children))
}
})
}
}
31 changes: 31 additions & 0 deletions util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const _ = require('lodash')

const extractText = children => {
return children
.map(child => {
if (!_.isEmpty(child.value)) {
return child.value
} else if (child.children && child.children.length > 0) {
return extractText(child.children)
} else {
return ''
}
})
.join(' ')
}

const getDefaultId = children => {
return formatDefaultId(extractText(children))
}

const formatDefaultId = value => {
return _.kebabCase(value.replaceAll(/\\s+/g, ' ').trim())
}

const setNodeId = (node, id) => {
if (!node.data) node.data = {}
if (!node.data.hProperties) node.data.hProperties = {}
node.data.id = node.data.hProperties.id = id
}

module.exports = { extractText, getDefaultId, formatDefaultId, setNodeId }

0 comments on commit 7b1d28d

Please # to comment.