UNPKG

2.3 kBJavaScriptView Raw
1'use strict';
2
3var htmlparser = require('htmlparser2')
4 , md = require('@textlint/markdown-to-ast');
5
6function addLinenos(lines, headers) {
7 var current = 0, line;
8
9 return headers.map(function (x) {
10 for (var lineno = current; lineno < lines.length; lineno++) {
11 line = lines[lineno];
12 if (new RegExp(x.text[0]).test(line)) {
13 current = lineno;
14 x.line = lineno;
15 x.name = x.text.join('');
16 return x
17 }
18 }
19
20 // in case we didn't find a matching line, which is odd,
21 // we'll have to assume it's right on the next line
22 x.line = ++current;
23 x.name = x.text.join('');
24 return x
25 })
26}
27
28function rankify(headers, max) {
29 return headers
30 .map(function (x) {
31 x.rank = parseInt(x.tag.slice(1), 10);
32 return x;
33 })
34 .filter(function (x) {
35 return x.rank <= max;
36 })
37}
38
39var go = module.exports = function (lines, maxHeaderLevel) {
40 var source = md.parse(lines.join('\n'))
41 .children
42 .filter(function(node) {
43 return node.type === md.Syntax.HtmlBlock || node.type === md.Syntax.Html;
44 })
45 .map(function (node) {
46 return node.raw;
47 })
48 .join('\n');
49
50 //var headers = [], grabbing = null, text = [];
51 var headers = [], grabbing = [], text = [];
52
53 var parser = new htmlparser.Parser({
54 onopentag: function (name, attr) {
55 // Short circuit if we're already inside a pre
56 if (grabbing[grabbing.length - 1] === 'pre') return;
57
58 if (name === 'pre' || (/h\d/).test(name)) {
59 grabbing.push(name);
60 }
61 },
62 ontext: function (text_) {
63 // Explicitly skip pre tags, and implicitly skip all others
64 if (grabbing.length === 0 ||
65 grabbing[grabbing.length - 1] === 'pre') return;
66
67 text.push(text_);
68 },
69 onclosetag: function (name) {
70 if (grabbing.length === 0) return;
71 if (grabbing[grabbing.length - 1] === name) {
72 var tag = grabbing.pop();
73 headers.push({ text: text, tag: tag });
74 text = [];
75 }
76 }
77 },
78 { decodeEntities: true })
79
80 parser.write(source);
81 parser.end();
82
83 headers = addLinenos(lines, headers)
84 // consider anything past h4 to small to warrant a link, may be made configurable in the future
85 headers = rankify(headers, maxHeaderLevel);
86 return headers;
87}