Skip to content

Commit 08d6dc2

Browse files
committed
Replace markdown strings with parsed ASTs
This eliminates the need for formatInlineTags and jsdoc-inline-lex, and simplifies the implementation of HTML themes.
1 parent 3883cb4 commit 08d6dc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+10350
-783
lines changed

lib/format_inline_tags.js

-27
This file was deleted.

lib/inline_tokenizer.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
3+
function makeTokenizer(type, regex) {
4+
var tokenizer = function (eat, value, silent) {
5+
var match = regex.exec(value);
6+
7+
if (!match) {
8+
return;
9+
}
10+
11+
if (silent) {
12+
return true;
13+
}
14+
15+
return eat(match[0])({
16+
'type': type,
17+
'url': match[1],
18+
'title': null,
19+
'children': [{
20+
'type': 'text',
21+
'value': match[2] || match[1]
22+
}]
23+
});
24+
};
25+
26+
tokenizer.notInLink = true;
27+
tokenizer.locator = function (value, fromIndex) {
28+
return value.indexOf('{@' + type, fromIndex);
29+
};
30+
31+
return tokenizer;
32+
}
33+
34+
var tokenizeLink = makeTokenizer('link', /^\{@link\s+(.+?)(?:[\s|](.*?))?\}/);
35+
var tokenizeTutorial = makeTokenizer('tutorial', /^\{@tutorial\s+(.+?)(?:[\s|](.*?))?\}/);
36+
37+
/**
38+
* A remark plugin that installs
39+
* [tokenizers](https://github.com/wooorm/remark/blob/master/doc/remarkplugin.3.md#function-tokenizereat-value-silent)
40+
* and [locators](https://github.com/wooorm/remark/blob/master/doc/remarkplugin.3.md#function-locatorvalue-fromindex)
41+
* for JSDoc inline `{@link}` and `{@tutorial}` tags.
42+
*
43+
* This does not handle the `[text]({@link url})` and `[text]({@tutorial url})` forms of these tags.
44+
* That's a JSDoc misfeature; just use regular markdown syntax instead: `[text](url)`.
45+
*
46+
* @param {Object} processor - remark instance
47+
* @returns {undefined}
48+
*/
49+
module.exports = function (processor) {
50+
var proto = processor.Parser.prototype;
51+
proto.inlineTokenizers.tokenizeLink = tokenizeLink;
52+
proto.inlineTokenizers.tokenizeTutorial = tokenizeTutorial;
53+
var methods = proto.inlineMethods;
54+
methods.splice(methods.indexOf('inlineText'), 0,
55+
'tokenizeLink', 'tokenizeTutorial');
56+
};

lib/output/markdown_ast.js

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
var remark = require('remark'),
2-
u = require('unist-builder'),
1+
var u = require('unist-builder'),
32
formatType = require('documentation-theme-utils').formatType,
4-
formatInlineTags = require('../format_inline_tags'),
53
hljs = require('highlight.js');
64

75
/**
@@ -37,7 +35,7 @@ function commentsToAST(comments, opts, callback) {
3735
u('text', ' '),
3836
!!param.type && u('strong', formatType(param.type)),
3937
u('text', ' ')
40-
].concat(remark.parse(formatInlineTags(param.description)).children)
38+
].concat(param.description ? param.description.children : [])
4139
.concat([
4240
!!param.default && u('paragraph', [
4341
u('text', ' (optional, default '),
@@ -74,7 +72,7 @@ function commentsToAST(comments, opts, callback) {
7472
u('strong', formatType(property.type)),
7573
u('text', ' ')
7674
]
77-
.concat(remark.parse(formatInlineTags(property.description)).children)
75+
.concat(property.description ? property.description.children: [])
7876
.filter(Boolean)),
7977
property.properties && propertyList(property.properties)
8078
].filter(Boolean));
@@ -87,7 +85,7 @@ function commentsToAST(comments, opts, callback) {
8785
language = hljsOptions.highlightAuto ?
8886
hljs.highlightAuto(example.description).language : 'javascript';
8987
return memo.concat(example.caption ?
90-
[u('paragraph', [u('emphasis', [u('text', example.caption)])])] :
88+
[u('paragraph', [u('emphasis', example.caption)])] :
9189
[]).concat([u('code', { lang: language }, example.description)]);
9290
}, []));
9391
}
@@ -98,7 +96,7 @@ function commentsToAST(comments, opts, callback) {
9896
u('text', 'Returns '),
9997
u('strong', formatType(returns.type)),
10098
u('text', ' ')
101-
].concat(remark.parse(formatInlineTags(returns.description)).children));
99+
].concat(returns.description ? returns.description.children : []));
102100
});
103101
}
104102

@@ -111,7 +109,7 @@ function commentsToAST(comments, opts, callback) {
111109
u('text', 'Throws '),
112110
u('strong', formatType(returns.type)),
113111
u('text', ' ')
114-
].concat(remark.parse(formatInlineTags(returns.description)).children))
112+
].concat(returns.description ? returns.description.children : []))
115113
]);
116114
}));
117115
}
@@ -161,7 +159,7 @@ function commentsToAST(comments, opts, callback) {
161159
return [u('heading', { depth: depth }, [u('text', comment.name || '')])]
162160
.concat(githubLink(comment))
163161
.concat(augmentsLink(comment))
164-
.concat(remark.parse(formatInlineTags(comment.description)).children)
162+
.concat(comment.description ? comment.description.children : [])
165163
.concat(paramSection(comment))
166164
.concat(propertySection(comment))
167165
.concat(examplesSection(comment))

lib/parse.js

+110-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
'use strict';
22

33
var doctrine = require('doctrine');
4+
var remark = require('remark');
5+
var inlineTokenizer = require('./inline_tokenizer');
6+
7+
function parseMarkdown(string) {
8+
return remark.use(inlineTokenizer).parse(string);
9+
}
410

511
var flatteners = {
612
'abstract': flattenBoolean,
@@ -10,22 +16,27 @@ var flatteners = {
1016
'alias': flattenName,
1117
'arg': synonym('param'),
1218
'argument': synonym('param'),
13-
'augments': collect('augments'),
19+
'augments': function (result, tag) {
20+
if (!result.augments) {
21+
result.augments = [];
22+
}
23+
result.augments.push(tag);
24+
},
1425
'author': flattenDescription,
1526
'borrows': todo,
1627
'callback': flattenDescription,
1728
'class': flattenTypedName,
18-
'classdesc': flattenDescription,
29+
'classdesc': flattenMarkdownDescription,
1930
'const': synonym('constant'),
2031
'constant': flattenTypedName,
2132
'constructor': synonym('class'),
2233
'constructs': todo,
23-
'copyright': flattenDescription,
34+
'copyright': flattenMarkdownDescription,
2435
'default': todo,
2536
'defaultvalue': synonym('default'),
26-
'deprecated': flattenDescription,
37+
'deprecated': flattenMarkdownDescription,
2738
'desc': synonym('description'),
28-
'description': flattenDescription,
39+
'description': flattenMarkdownDescription,
2940
'emits': synonym('fires'),
3041
'enum': todo,
3142
'event': flattenDescription,
@@ -47,7 +58,7 @@ var flatteners = {
4758
};
4859

4960
if (tag.caption) {
50-
example.caption = tag.caption;
61+
example.caption = parseMarkdown(tag.caption);
5162
}
5263

5364
result.examples.push(example);
@@ -98,12 +109,50 @@ var flatteners = {
98109
'namespace': flattenTypedName,
99110
'override': flattenBoolean,
100111
'overview': synonym('file'),
101-
'param': collect('params'),
112+
'param': function (result, tag) {
113+
if (!result.params) {
114+
result.params = [];
115+
}
116+
117+
var param = {
118+
name: tag.name,
119+
lineNumber: tag.lineNumber // TODO: remove
120+
};
121+
122+
if (tag.description) {
123+
param.description = parseMarkdown(tag.description);
124+
}
125+
126+
if (tag.type) {
127+
param.type = tag.type;
128+
}
129+
130+
result.params.push(param);
131+
},
102132
'private': function (result) {
103133
result.access = 'private';
104134
},
105135
'prop': synonym('property'),
106-
'property': collect('properties'),
136+
'property': function (result, tag) {
137+
if (!result.properties) {
138+
result.properties = [];
139+
}
140+
141+
var property = {
142+
name: tag.name,
143+
lineNumber: tag.lineNumber // TODO: remove
144+
};
145+
146+
if (tag.description) {
147+
property.description = parseMarkdown(tag.description);
148+
}
149+
150+
if (tag.type) {
151+
property.type = tag.type;
152+
}
153+
154+
result.properties.push(property);
155+
},
107156
'protected': function (result) {
108157
result.access = 'protected';
109158
},
@@ -113,16 +162,56 @@ var flatteners = {
113162
'readonly': flattenBoolean,
114163
'requires': todo,
115164
'return': synonym('returns'),
116-
'returns': collect('returns'),
117-
'see': collect('sees', true),
165+
'returns': function (result, tag) {
166+
if (!result.returns) {
167+
result.returns = [];
168+
}
169+
170+
var returns = {
171+
description: parseMarkdown(tag.description)
172+
};
173+
174+
if (tag.type) {
175+
returns.type = tag.type;
176+
}
177+
178+
result.returns.push(returns);
179+
},
180+
'see': function (result, tag) {
181+
if (!result.sees) {
182+
result.sees = [];
183+
}
184+
result.sees.push(parseMarkdown(tag.description));
185+
},
118186
'since': flattenDescription,
119187
'static': function (result) {
120188
result.scope = 'static';
121189
},
122-
'summary': flattenDescription,
190+
'summary': flattenMarkdownDescription,
123191
'this': todo,
124-
'throws': collect('throws'),
125-
'todo': collect('todos', true),
192+
'throws': function (result, tag) {
193+
if (!result.throws) {
194+
result.throws = [];
195+
}
196+
197+
var throws = {};
198+
199+
if (tag.description) {
200+
throws.description = parseMarkdown(tag.description);
201+
}
202+
203+
if (tag.type) {
204+
throws.type = tag.type;
205+
}
206+
207+
result.throws.push(throws);
208+
},
209+
'todo': function (result, tag) {
210+
if (!result.todos) {
211+
result.todos = [];
212+
}
213+
result.todos.push(parseMarkdown(tag.description));
214+
},
126215
'tutorial': todo,
127216
'type': todo,
128217
'typedef': flattenTypedName,
@@ -136,19 +225,6 @@ var flatteners = {
136225

137226
function todo() {}
138227

139-
function collect(key, description) {
140-
return function (result, tag) {
141-
if (!result[key]) {
142-
result[key] = [];
143-
}
144-
if (description) {
145-
result[key].push(tag.description);
146-
} else {
147-
result[key].push(tag);
148-
}
149-
};
150-
}
151-
152228
function synonym(key) {
153229
return function (result, tag) {
154230
return flatteners[key](result, tag, key);
@@ -167,6 +243,10 @@ function flattenDescription(result, tag, key) {
167243
result[key] = tag.description;
168244
}
169245

246+
function flattenMarkdownDescription(result, tag, key) {
247+
result[key] = parseMarkdown(tag.description);
248+
}
249+
170250
function flattenTypedName(result, tag, key) {
171251
result[key] = {
172252
name: tag.name
@@ -269,6 +349,10 @@ function parseJSDoc(comment, loc, context) {
269349
result.context = context;
270350
result.errors = [];
271351

352+
if (result.description) {
353+
result.description = parseMarkdown(result.description);
354+
}
355+
272356
result.tags.forEach(function (tag) {
273357
if (tag.errors) {
274358
for (var j = 0; j < tag.errors.length; j++) {

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@
2222
"debounce": "^1.0.0",
2323
"disparity": "^2.0.0",
2424
"doctrine": "^1.1.0",
25-
"documentation-theme-default": "3.0.0-beta",
25+
"documentation-theme-default": "documentationjs/documentation-theme-default#markdown",
2626
"documentation-theme-utils": "^2.0.2",
2727
"events": "^1.1.0",
2828
"extend": "^3.0.0",
2929
"get-comments": "^1.0.1",
3030
"git-url-parse": "^6.0.1",
3131
"highlight.js": "^9.1.0",
3232
"js-yaml": "^3.3.1",
33-
"jsdoc-inline-lex": "^1.0.1",
3433
"mdast-util-inject": "^1.1.0",
3534
"micromatch": "^2.1.6",
3635
"mime": "^1.3.4",
@@ -60,7 +59,8 @@
6059
"lodash": "^4.3.0",
6160
"mock-fs": "^3.5.0",
6261
"tap": "^5.4.4",
63-
"tmp": "0.0.28"
62+
"tmp": "0.0.28",
63+
"unist-util-visit": "^1.0.1"
6464
},
6565
"keywords": [
6666
"documentation",

0 commit comments

Comments
 (0)