Files
30-seconds-of-code/node_modules/mdast-util-toc/lib/search.js
2019-08-20 15:52:05 +02:00

98 lines
2.3 KiB
JavaScript

/**
* @author Titus Wormer
* @copyright 2015 Titus Wormer
* @license MIT
* @module mdast:toc
* @fileoverview Generate a Table of Contents (TOC) from a given Markdown file.
*/
/* Expose. */
module.exports = search;
/* Dependencies */
var toString = require('mdast-util-to-string');
var visit = require('unist-util-visit');
var slugs = require('github-slugger')();
var isClosingHeading = require('./is-closing-heading');
var isOpeningHeading = require('./is-opening-heading');
/* Constants. */
var HEADING = 'heading';
/**
* Search a node for a location.
*
* @param {Node} root - Parent to search in.
* @param {RegExp} expression - Heading-content to search
* for.
* @param {number} maxDepth - Maximum-depth to include.
* @return {Object} - Results.
*/
function search(root, expression, maxDepth) {
var length = root.children.length;
var depth = null;
var lookingForToc = expression !== null;
var map = [];
var headingIndex;
var closingIndex;
if (!lookingForToc) {
headingIndex = -1;
}
slugs.reset();
/*
* Visit all headings in `root`.
* We `slug` all headings (to account for duplicates),
* but only create a TOC from top-level headings.
*/
visit(root, HEADING, function(child, index, parent) {
var value = toString(child);
var id =
child.data && child.data.hProperties && child.data.hProperties.id;
id = slugs.slug(id || value);
if (parent !== root) {
return;
}
if (lookingForToc) {
if (isClosingHeading(child, depth)) {
closingIndex = index;
lookingForToc = false;
}
if (isOpeningHeading(child, depth, expression)) {
headingIndex = index + 1;
depth = child.depth;
}
}
if (!lookingForToc && value && child.depth <= maxDepth) {
map.push({
depth: child.depth,
value: value,
id: id
});
}
});
if (headingIndex && !closingIndex) {
closingIndex = length + 1;
}
if (headingIndex === undefined) {
headingIndex = -1;
closingIndex = -1;
map = [];
}
return {
index: headingIndex,
endIndex: closingIndex,
map: map
};
}