From 4d383ed5734b6eb35f408368a7ca06e94f04a38b Mon Sep 17 00:00:00 2001 From: Elian Ibaj Date: Tue, 27 Feb 2018 18:18:44 +0100 Subject: [PATCH] Add function to generate TOC from document headings --- lib/core/getTOC.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 lib/core/getTOC.js diff --git a/lib/core/getTOC.js b/lib/core/getTOC.js new file mode 100644 index 000000000000..182d88058241 --- /dev/null +++ b/lib/core/getTOC.js @@ -0,0 +1,52 @@ +const Remarkable = require('remarkable'); +const toSlug = require('./toSlug'); + +const tagToLevel = tag => Number(tag.slice(1)); + +/** + * Returns a table of content from the headings + * + * @return array + * Array of heading objects with `hashLink`, `text` and `children` fields + * + */ +module.exports = (content, headingTags = 'h2', subHeadingTags = 'h3') => { + const headingLevels = [].concat(headingTags).map(tagToLevel); + const subHeadingLevels = subHeadingTags + ? [].concat(subHeadingTags).map(tagToLevel) + : []; + + const md = new Remarkable(); + const tokens = md.parse(content, {}); + const headings = []; + for (let i = 0; i < tokens.length; i++) { + if ( + tokens[i].type == 'heading_open' && + headingLevels.concat(subHeadingLevels).includes(tokens[i].hLevel) + ) { + headings.push({ + hLevel: tokens[i].hLevel, + text: tokens[i + 1].content, + }); + } + } + + const toc = []; + let current; + headings.forEach(heading => { + const entry = { + hashLink: toSlug(heading.text), + text: heading.text, + children: [], + }; + + if (headingLevels.includes(heading.hLevel)) { + toc.push(entry); + current = entry; + } else { + current && current.children.push(entry); + } + }); + + return toc; +};