diff --git a/.gitignore b/.gitignore index f06235c..8a65301 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +.nyc_output +coverage node_modules dist diff --git a/CHANGELOG.md b/CHANGELOG.md index 33555f7..7a43d44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# 4.0.0 + +* Upgraded to remark-html 5.x. + +## Breaking changes + +* `opts.attributes` is now named `opts.linkProperties`. +* `opts.template` has been replaced with `opts.content`; instead of supplying + a HTML string here, you can specify either a single HAST node or an array + of them. This makes the module more suitable for working with virtual node + consumers, such as React. + # 3.0.1 * Upgraded to remark 5.x, this module will work the same using either version. diff --git a/README.md b/README.md index 61a075f..8633eb2 100644 --- a/README.md +++ b/README.md @@ -40,29 +40,30 @@ console.log(result); #### options -##### attributes - -Type: `object` - -By default, when using the `append` or `prepend` behaviour, this will add -`aria-hidden="false"` to the anchor. When using the `wrap` behaviour, this is -left empty for you to add any extra HTML attributes. - ##### behaviour Type: `string` Default: `prepend` Set this to `prepend` to inject the link before the heading text; `append` after -it, and `wrap` to wrap the whole heading text with the link. Note that the -`wrap` option doesn't apply any value set by the `template` option. +it, and `wrap` to wrap the whole heading text with the link. Note that supplying +`wrap` will ignore any value defined by the `template` option. -##### template +##### content -Type: `string` -Default: `` +Type: `Object|Array` +Default: `{type: 'element', tagName: 'span', properties: {className: [icon, `${icon}-${link}`]} }` -The template used by the `append` & `prepend` behaviours. +Supply a list of HAST nodes or a single node here. For further details, please +refer to the specification at https://github.com/wooorm/hast. + +##### linkProperties + +Type: `object` + +By default, when using the `append` or `prepend` behaviour, this will add +`aria-hidden="false"` to the anchor. When using the `wrap` behaviour, this is +left empty for you to add any extra HTML attributes. ## Contributing diff --git a/package.json b/package.json index 2deee36..c6df059 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,9 @@ "scripts": { "pretest": "eslint src", "prepublish": "del-cli dist && babel src --out-dir dist --ignore /__tests__/", - "test": "ava src/__tests__", - "test-012": "ava src/__tests__" + "report": "nyc report --reporter=html", + "test": "nyc ava", + "test-012": "nyc ava" }, "keywords": [ "headings", @@ -36,10 +37,11 @@ "eslint-plugin-babel": "^3.3.0", "eslint-plugin-import": "^1.10.2", "remark": "^5.0.1", - "remark-html": "^3.0.0", - "remark-slug": "^4.1.0" + "remark-html": "^5.0.0", + "remark-slug": "^4.1.0", + "nyc": "^7.0.0" }, - "homepage": "https://github.com/ben-eb/mdast-autolink-headings", + "homepage": "https://github.com/ben-eb/remark-autolink-headings", "author": { "name": "Ben Briggs", "email": "beneb.info@gmail.com", @@ -47,7 +49,6 @@ }, "repository": "ben-eb/remark-autolink-headings", "dependencies": { - "object-assign": "^4.0.1", "unist-util-visit": "^1.0.1" }, "eslintConfig": { diff --git a/src/__tests__/index.js b/src/__tests__/index.js index 08403fe..2abe481 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -15,6 +15,12 @@ test('should autolink headings', t => { }); }); +test('should accept custom content', t => { + const md = '# method'; + const {contents} = remark().use(slug).use(html).use(headings, {content: {type: 'text', value: '#'}}).process(md); + t.deepEqual(contents, '

method

\n'); +}); + test('should do nothing if slugs are not used', t => { let {contents} = remark().use(headings).use(html).process(base('input.md')); t.deepEqual(contents, base('output.html')); diff --git a/src/index.js b/src/index.js index b6fb9b5..95541d3 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,16 @@ -import assign from 'object-assign'; import visit from 'unist-util-visit'; -let base = (node, callback) => { - let data = node.data || {}; +const icon = 'icon'; +const link = 'link'; +const wrap = 'wrap'; + +const methodMap = { + prepend: 'unshift', + append: 'push', +}; + +const base = (node, callback) => { + const {data} = node; if (!data || !data.htmlAttributes || !data.htmlAttributes.id) { return; } @@ -10,49 +18,55 @@ let base = (node, callback) => { return callback('#' + data.htmlAttributes.id); }; +const contentDefaults = { + type: 'element', + tagName: 'span', + properties: {className: [icon, `${icon}-${link}`]}, +}; + export default function attacher (remark, opts = {}) { - opts = assign({ + let {linkProperties, behaviour, content} = { behaviour: 'prepend', - template: '', - }, opts); - - let behaviour = opts.behaviour; - - let methodMap = { - prepend: 'unshift', - append: 'push', + content: contentDefaults, + ...opts, }; - function inject (node) { - return base(node, id => { + if (behaviour !== wrap && !linkProperties) { + linkProperties = {'aria-hidden': true}; + } + + function injectNode (node) { + return base(node, url => { + if (!Array.isArray(content)) { + content = [content]; + } node.children[methodMap[behaviour]]({ - type: 'link', - url: id, + type: link, + url, title: null, - children: [], data: { - htmlContent: opts.template, - htmlAttributes: opts.attributes || {'aria-hidden': true}, + hProperties: linkProperties, + hChildren: content, }, }); }); } - function wrap (node) { - return base(node, id => { - let children = node.children; + function wrapNode (node) { + return base(node, url => { + const {children} = node; node.children = [{ - type: 'link', - url: id, + type: link, + url, title: null, - children: children, + children, data: { - htmlAttributes: opts.attributes, + hProperties: linkProperties, }, }]; }); } - return ast => visit(ast, 'heading', behaviour === 'wrap' ? wrap : inject); + return ast => visit(ast, 'heading', behaviour === wrap ? wrapNode : injectNode); }