Skip to content

Commit a6a5917

Browse files
committed
feat(markdown): Add table of contents support for Markdown mode
Fixes #220
1 parent 2ae5d8f commit a6a5917

File tree

7 files changed

+212
-10
lines changed

7 files changed

+212
-10
lines changed

Diff for: docs/NODE_API.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
22

3+
### Table of Contents
4+
5+
- [build](#build)
6+
- [buildSync](#buildsync)
7+
- [lint](#lint)
8+
- [formats](#formats)
9+
- [formats.html](#formatshtml)
10+
- [formats.markdown](#formatsmarkdown)
11+
- [formats.json](#formatsjson)
12+
313
## build
414

515
Generate JavaScript documentation as a list of parsed JSDoc

Diff for: lib/commands/build.js

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ module.exports.builder = extend({},
2626
default: 'json',
2727
choices: ['json', 'md', 'remark', 'html']
2828
},
29+
'markdown-toc': {
30+
describe: 'include a table of contents in markdown output',
31+
default: 'stdout',
32+
type: 'boolean'
33+
},
2934
output: {
3035
describe: 'output location. omit for stdout, otherwise is a filename ' +
3136
'for single-file outputs and a directory name for multi-file outputs like html',
@@ -66,6 +71,7 @@ module.exports.handler = function build(argv, callback) {
6671
version: argv['project-version'] || (argv.package || {}).version,
6772
theme: argv.theme,
6873
paths: argv.paths,
74+
'markdown-toc': argv['markdown-toc'],
6975
hljs: argv.hljs || {}
7076
};
7177

Diff for: lib/output/markdown.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ var remark = require('remark'),
2626
* });
2727
*/
2828
module.exports = function (comments, options, callback) {
29-
var processor = remark().use(toc);
29+
var processor = remark().use(toc, {
30+
tight: true
31+
});
3032
markdownAST(comments, options, function (err, ast) {
3133
var processedAST = processor.run(ast);
3234
return callback(null, processor.stringify(processedAST));

Diff for: lib/output/markdown_ast.js

+11-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var u = require('unist-builder'),
1414
* @param {Function} callback called with AST
1515
* @returns {undefined} calls callback
1616
*/
17-
function commentsToAST(comments, options, callback) {
17+
function markdownAST(comments, options, callback) {
1818

1919
// Configure code highlighting
2020
var hljsOptions = (options || {}).hljs || {},
@@ -33,6 +33,10 @@ function commentsToAST(comments, options, callback) {
3333
u('html', '<!-- Generated by documentation.js. Update this documentation by updating the source code. -->')
3434
];
3535

36+
var tableOfContentsHeading = [
37+
u('heading', { depth: 3 }, [u('text', 'Table of Contents')])
38+
];
39+
3640
/**
3741
* Generate an AST chunk for a comment at a given depth: this is
3842
* split from the main function to handle hierarchially nested comments
@@ -203,9 +207,11 @@ function commentsToAST(comments, options, callback) {
203207
}
204208

205209
return callback(null, rerouteLinks(linkerStack.link,
206-
u('root', generatorComment.concat(comments.reduce(function (memo, comment) {
207-
return memo.concat(generate(2, comment));
208-
}, [])))));
210+
u('root', generatorComment
211+
.concat(options['markdown-toc'] ? tableOfContentsHeading : [])
212+
.concat(comments.reduce(function (memo, comment) {
213+
return memo.concat(generate(2, comment));
214+
}, [])))));
209215
}
210216

211-
module.exports = commentsToAST;
217+
module.exports = markdownAST;

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
},
8686
"scripts": {
8787
"lint": "eslint bin lib index.js test",
88-
"doc": "./bin/documentation.js build index.js -f md --access=public > docs/NODE_API.md",
88+
"doc": "./bin/documentation.js build index.js -f md --access=public --markdown-toc > docs/NODE_API.md",
8989
"changelog": "standard-changelog -i CHANGELOG.md -w",
9090
"self-lint": "node ./bin/documentation.js lint",
9191
"test": "npm run lint && npm run self-lint && tap -t 120 --coverage --nyc-arg=--cache test/*.js test/lib test/streams"

Diff for: test/fixture/es6.output-toc.md

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
2+
3+
### Table of Contents
4+
5+
- [destructure](#destructure)
6+
- [destructure](#destructure-1)
7+
- [multiply](#multiply)
8+
- [Sink](#sink)
9+
- [staticProp](#staticprop)
10+
- [empty](#empty)
11+
- [aGetter](#agetter)
12+
- [constructor](#constructor)
13+
- [hello](#hello)
14+
- [makeABasket](#makeabasket)
15+
- [makeASink](#makeasink)
16+
- [functionWithRest](#functionwithrest)
17+
- [functionWithRestAndType](#functionwithrestandtype)
18+
- [foo](#foo)
19+
- [es6.input](#es6input)
20+
- [veryImportantTransform](#veryimportanttransform)
21+
- [iAmProtected](#iamprotected)
22+
- [iAmPublic](#iampublic)
23+
- [execute](#execute)
24+
- [isArrayEqualWith](#isarrayequalwith)
25+
26+
## destructure
27+
28+
This function destructures with defaults. It should not
29+
have any parameter descriptions.
30+
31+
**Parameters**
32+
33+
- `$0` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** (optional, default `{}`)
34+
- `$0.phoneNumbers` (optional, default `[]`)
35+
- `$0.emailAddresses` (optional, default `[]`)
36+
- `$0.params` **...any**
37+
38+
## destructure
39+
40+
Similar, but with an array
41+
42+
**Parameters**
43+
44+
- `$0` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)**
45+
- `$0.a`
46+
- `$0.b`
47+
- `$0.c`
48+
49+
**Examples**
50+
51+
```javascript
52+
destructure([1, 2, 3])
53+
```
54+
55+
## multiply
56+
57+
This function returns the number one.
58+
59+
**Parameters**
60+
61+
- `a` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>** an array of numbers
62+
- `b`
63+
64+
Returns **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** numberone
65+
66+
## Sink
67+
68+
This is a sink
69+
70+
### staticProp
71+
72+
This is a property of the sink.
73+
74+
### empty
75+
76+
Is it empty
77+
78+
### aGetter
79+
80+
This is a getter method: it should be documented
81+
as a property.
82+
83+
### constructor
84+
85+
**Parameters**
86+
87+
- `height` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the height of the thing
88+
- `width` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the width of the thing
89+
90+
### hello
91+
92+
This method says hello
93+
94+
## makeABasket
95+
96+
This method returns a basket. The type should not be linked.
97+
98+
Returns **Basket** a basket
99+
100+
## makeASink
101+
102+
This method returns a [sink](#sink). The type should be linked.
103+
It takes a [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) which should also be linked.
104+
105+
Returns **[Sink](#sink)** a sink
106+
107+
## functionWithRest
108+
109+
This function takes rest params
110+
111+
**Parameters**
112+
113+
- `someParams` **...any**
114+
115+
## functionWithRestAndType
116+
117+
So does this one, with types
118+
119+
**Parameters**
120+
121+
- `someParams` **...[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)**
122+
123+
## foo
124+
125+
This is an async method
126+
127+
## es6.input
128+
129+
This function returns the number one.
130+
131+
Returns **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** numberone
132+
133+
## veryImportantTransform
134+
135+
This tests our support of optional parameters in ES6
136+
137+
**Parameters**
138+
139+
- `foo` (optional, default `'bar'`)
140+
141+
## iAmProtected
142+
143+
A protected function
144+
145+
## iAmPublic
146+
147+
A public function
148+
149+
## execute
150+
151+
This is re-exported
152+
153+
## isArrayEqualWith
154+
155+
Regression check for #498
156+
157+
**Parameters**
158+
159+
- `array1` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;T>**
160+
- `array2` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;T>**
161+
- `compareFunction` **function (a: T, b: T): [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** (optional, default `(a: T, b: T): boolean => a === b`)
162+
163+
Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**

Diff for: test/test.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,25 @@ test('outputs', function (ttt) {
147147
});
148148
});
149149

150-
tt.test('markdown AST', function (t) {
151-
outputMarkdownAST(_.cloneDeep(result), {}, function (err, result) {
150+
if (file.match(/es6.input.js/)) {
151+
tt.test('markdown AST', function (t) {
152+
outputMarkdown(_.cloneDeep(result), { 'markdown-toc': true }, function (err, result) {
153+
t.ifError(err);
154+
var outputfile = file.replace('.input.js', '.output-toc.md');
155+
if (UPDATE) {
156+
fs.writeFileSync(outputfile, result, 'utf8');
157+
}
158+
var expect = fs.readFileSync(outputfile, 'utf8');
159+
t.equal(result.toString(), expect, 'markdown output correct');
160+
t.end();
161+
});
162+
});
163+
}
164+
165+
tt.test('markdown TOC', function (t) {
166+
outputMarkdownAST(_.cloneDeep(result), { 'markdown-toc': true }, function (err, result) {
152167
t.ifError(err);
153-
var outputfile = file.replace('.input.js', '.output.md.json');
168+
var outputfile = file.replace('.input.js', '.output-toc.md.json');
154169
if (UPDATE) {
155170
fs.writeFileSync(outputfile, JSON.stringify(result, null, 2), 'utf8');
156171
}

0 commit comments

Comments
 (0)