comment-parser 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -1
- package/README.md +12 -11
- package/package.json +2 -2
- package/parser.js +31 -34
- package/tests/parse.spec.js +53 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# v0.3.2
|
|
2
|
+
- fix RegExp for `description` extraction to allow $ char
|
|
3
|
+
|
|
1
4
|
# v0.3.1
|
|
2
5
|
- use `readable-stream` fro Node 0.8 comatibility
|
|
3
6
|
- allow to pass optional parameters to `parse.file(path [,opts], done)`
|
|
@@ -39,4 +42,4 @@
|
|
|
39
42
|
|
|
40
43
|
# v0.1.0
|
|
41
44
|
|
|
42
|
-
Initial implementation
|
|
45
|
+
Initial implementation
|
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ Also you can parse entire file with `parse.file('path/to/file', callback)` or ac
|
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
In case you need to parse tags in different way you can pass `opts.parsers = [parser1, ..., parserN]`, where each parser is `function name(str:String, data:Object):{source:String, data:Object}`.
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
Each parser function takes string left after previous parsers applied and data produced by them. And returns `null` or `{source: '', data:{}}` where `source` is consumed substring and `data` is a payload with tag node fields.
|
|
79
79
|
|
|
80
80
|
Tag node data is build by merging result bits from all parsers. Here is some example that is not doing actual parsing but is demonstrating the flow:
|
|
@@ -86,23 +86,23 @@ Tag node data is build by merging result bits from all parsers. Here is some exa
|
|
|
86
86
|
*/
|
|
87
87
|
parse(source, {parsers: [
|
|
88
88
|
// takes entire string
|
|
89
|
-
function parse_tag(str, data) {
|
|
90
|
-
return {source: ' @tag', data: {tag: 'tag'}};
|
|
91
|
-
},
|
|
89
|
+
function parse_tag(str, data) {
|
|
90
|
+
return {source: ' @tag', data: {tag: 'tag'}};
|
|
91
|
+
},
|
|
92
92
|
// parser throwing exception
|
|
93
93
|
function check_tag(str, data) {
|
|
94
|
-
if (allowed_tags.indexOf(data.tag) === -1) {
|
|
94
|
+
if (allowed_tags.indexOf(data.tag) === -1) {
|
|
95
95
|
throw new Error('Unrecognized tag "' + data.tag + '"');
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
// takes the rest of the string after ' @tag''
|
|
99
|
-
function parse_name1(str, data) {
|
|
100
|
-
return {source: ' name', data: {name: 'name1'}};
|
|
99
|
+
function parse_name1(str, data) {
|
|
100
|
+
return {source: ' name', data: {name: 'name1'}};
|
|
101
101
|
},
|
|
102
102
|
// alternative name parser
|
|
103
|
-
function parse_name2(str, data) {
|
|
104
|
-
return {source: ' name', data: {name: 'name2'}};
|
|
105
|
-
}
|
|
103
|
+
function parse_name2(str, data) {
|
|
104
|
+
return {source: ' name', data: {name: 'name2'}};
|
|
105
|
+
}
|
|
106
106
|
]});
|
|
107
107
|
```
|
|
108
108
|
|
|
@@ -135,9 +135,10 @@ This would produce following:
|
|
|
135
135
|
## Contributors
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
- [Sergii Iavorskyi](https://github.com/yavorskiy)
|
|
139
138
|
- [Alexej Yaroshevich](https://github.com/zxqfox)
|
|
139
|
+
- [Evgeny Reznichenko](https://github.com/zxcabs)
|
|
140
140
|
- [Jordan Harband](https://github.com/ljharb)
|
|
141
|
+
- [Sergii Iavorskyi](https://github.com/yavorskiy)
|
|
141
142
|
|
|
142
143
|
|
|
143
144
|
Happy coding :)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comment-parser",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Generic JSDoc-like comment parser. ",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
20
20
|
"test": "jshint --reporter node_modules/jshint-stylish/stylish.js index.js && mocha tests/*",
|
|
21
|
-
"watch": "nodemon -q -w index.js -w tests/ -x npm test"
|
|
21
|
+
"watch": "nodemon -q -w index.js -w parser.js -w tests/ -x npm test"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
package/parser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
var RE_COMMENT_START = /^\s*\/\*\*\s*$/m;
|
|
3
|
-
var RE_COMMENT_LINE = /^\s*\*(?:\s|$)/m;
|
|
3
|
+
var RE_COMMENT_LINE = /^\s*\*(?:\s(\s*)|$)/m;
|
|
4
4
|
var RE_COMMENT_END = /^\s*\*\/\s*$/m;
|
|
5
5
|
var RE_COMMENT_1LINE = /^\s*\/\*\*\s*(.*)\s*\*\/\s*$/;
|
|
6
6
|
|
|
@@ -115,7 +115,7 @@ PARSERS.parse_name = function parse_name(str, data) {
|
|
|
115
115
|
PARSERS.parse_description = function parse_description(str, data) {
|
|
116
116
|
if (data.errors && data.errors.length) { return null; }
|
|
117
117
|
|
|
118
|
-
var result = str.match(/^\s+(
|
|
118
|
+
var result = str.match(/^\s+((.|\s)+)?/);
|
|
119
119
|
|
|
120
120
|
if (result) {
|
|
121
121
|
return {
|
|
@@ -143,10 +143,7 @@ function parse_tag(str, parsers) {
|
|
|
143
143
|
|
|
144
144
|
try {
|
|
145
145
|
result = parser(state.source, merge({}, state.data));
|
|
146
|
-
// console.log('----------------');
|
|
147
|
-
// console.log(parser.name, ':', result);
|
|
148
146
|
} catch (err) {
|
|
149
|
-
// console.warn('Parser "%s" failed: %s', parser.name, err.message);
|
|
150
147
|
state.data.errors = (state.data.errors || [])
|
|
151
148
|
.concat(parser.name + ': ' + err.message);
|
|
152
149
|
}
|
|
@@ -175,10 +172,15 @@ function parse_tag(str, parsers) {
|
|
|
175
172
|
*/
|
|
176
173
|
function parse_block(source, opts) {
|
|
177
174
|
|
|
175
|
+
function trim(s) {
|
|
176
|
+
return opts.trim ? s.trim() : s;
|
|
177
|
+
}
|
|
178
|
+
|
|
178
179
|
var source_str = source
|
|
179
|
-
.map(function(line) { return line.source; })
|
|
180
|
-
.join('\n')
|
|
181
|
-
|
|
180
|
+
.map(function(line) { return trim(line.source); })
|
|
181
|
+
.join('\n');
|
|
182
|
+
|
|
183
|
+
source_str = trim(source_str);
|
|
182
184
|
|
|
183
185
|
var start = source[0].number;
|
|
184
186
|
|
|
@@ -186,9 +188,9 @@ function parse_block(source, opts) {
|
|
|
186
188
|
// we assume tag starts with "@"
|
|
187
189
|
source = source
|
|
188
190
|
.reduce(function(tags, line) {
|
|
189
|
-
line.source = line.source
|
|
191
|
+
line.source = trim(line.source);
|
|
190
192
|
|
|
191
|
-
if (line.source.match(
|
|
193
|
+
if (line.source.match(/^\s*@(\w+)/)) {
|
|
192
194
|
tags.push({source: [line.source], line: line.number});
|
|
193
195
|
} else {
|
|
194
196
|
var tag = tags[tags.length - 1];
|
|
@@ -198,7 +200,7 @@ function parse_block(source, opts) {
|
|
|
198
200
|
return tags;
|
|
199
201
|
}, [{source: []}])
|
|
200
202
|
.map(function(tag) {
|
|
201
|
-
tag.source = tag.source.join('\n')
|
|
203
|
+
tag.source = trim(tag.source.join('\n'));
|
|
202
204
|
return tag;
|
|
203
205
|
});
|
|
204
206
|
|
|
@@ -211,12 +213,7 @@ function parse_block(source, opts) {
|
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
var tags = source.reduce(function(tags, tag) {
|
|
214
|
-
var tag_node = parse_tag(tag.source, opts.parsers
|
|
215
|
-
PARSERS.parse_tag,
|
|
216
|
-
PARSERS.parse_type,
|
|
217
|
-
PARSERS.parse_name,
|
|
218
|
-
PARSERS.parse_description
|
|
219
|
-
]);
|
|
216
|
+
var tag_node = parse_tag(tag.source, opts.parsers);
|
|
220
217
|
|
|
221
218
|
if (!tag_node) { return tags; }
|
|
222
219
|
|
|
@@ -258,10 +255,7 @@ function parse_block(source, opts) {
|
|
|
258
255
|
|
|
259
256
|
return tags.concat(tag_node);
|
|
260
257
|
}, []);
|
|
261
|
-
|
|
262
|
-
// console.log('-----------');
|
|
263
|
-
// console.log(description, tags);
|
|
264
|
-
|
|
258
|
+
|
|
265
259
|
return {
|
|
266
260
|
tags : tags,
|
|
267
261
|
line : start,
|
|
@@ -274,10 +268,20 @@ function parse_block(source, opts) {
|
|
|
274
268
|
* Produces `extract` function with internal state initialized
|
|
275
269
|
*/
|
|
276
270
|
function mkextract(opts) {
|
|
277
|
-
|
|
278
271
|
var chunk = null;
|
|
279
272
|
var number = 0;
|
|
280
273
|
|
|
274
|
+
opts = merge({}, {
|
|
275
|
+
trim : true,
|
|
276
|
+
dotted_names : false,
|
|
277
|
+
parsers : [
|
|
278
|
+
PARSERS.parse_tag,
|
|
279
|
+
PARSERS.parse_type,
|
|
280
|
+
PARSERS.parse_name,
|
|
281
|
+
PARSERS.parse_description
|
|
282
|
+
]
|
|
283
|
+
}, opts || {});
|
|
284
|
+
|
|
281
285
|
/**
|
|
282
286
|
* Cumulatively reading lines until they make one comment block
|
|
283
287
|
* Returns block object or null.
|
|
@@ -287,8 +291,6 @@ function mkextract(opts) {
|
|
|
287
291
|
// if oneliner
|
|
288
292
|
// then parse it immediately
|
|
289
293
|
if (line.match(RE_COMMENT_1LINE)) {
|
|
290
|
-
// console.log('line (1)', line);
|
|
291
|
-
// console.log(' clean:', line.replace(RE_COMMENT_1LINE, '$1'));
|
|
292
294
|
return parse_block([{
|
|
293
295
|
source: line.replace(RE_COMMENT_1LINE, '$1'),
|
|
294
296
|
number: number}], opts);
|
|
@@ -299,8 +301,6 @@ function mkextract(opts) {
|
|
|
299
301
|
// if start of comment
|
|
300
302
|
// then init the chunk
|
|
301
303
|
if (line.match(RE_COMMENT_START)) {
|
|
302
|
-
// console.log('line (1)', line);
|
|
303
|
-
// console.log(' clean:', line.replace(RE_COMMENT_START, ''));
|
|
304
304
|
chunk = [{source: line.replace(RE_COMMENT_START, ''), number: number - 1}];
|
|
305
305
|
return null;
|
|
306
306
|
}
|
|
@@ -308,17 +308,16 @@ function mkextract(opts) {
|
|
|
308
308
|
// if comment line and chunk started
|
|
309
309
|
// then append
|
|
310
310
|
if (chunk && line.match(RE_COMMENT_LINE)) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
311
|
+
chunk.push({
|
|
312
|
+
number: number - 1,
|
|
313
|
+
source: line.replace(RE_COMMENT_LINE, opts.trim ? '' : '$1')
|
|
314
|
+
});
|
|
314
315
|
return null;
|
|
315
316
|
}
|
|
316
317
|
|
|
317
318
|
// if comment end and chunk started
|
|
318
319
|
// then parse the chunk and push
|
|
319
320
|
if (chunk && line.match(RE_COMMENT_END)) {
|
|
320
|
-
// console.log('line (3)', line);
|
|
321
|
-
// console.log(' clean:', line.replace(RE_COMMENT_END, ''));
|
|
322
321
|
chunk.push({source: line.replace(RE_COMMENT_END, ''), number: number - 1});
|
|
323
322
|
return parse_block(chunk, opts);
|
|
324
323
|
}
|
|
@@ -332,8 +331,6 @@ function mkextract(opts) {
|
|
|
332
331
|
/* ------- Public API ------- */
|
|
333
332
|
|
|
334
333
|
module.exports = function parse(source, opts) {
|
|
335
|
-
opts = opts || {};
|
|
336
|
-
|
|
337
334
|
var block;
|
|
338
335
|
var blocks = [];
|
|
339
336
|
var extract = mkextract(opts);
|
|
@@ -350,4 +347,4 @@ module.exports = function parse(source, opts) {
|
|
|
350
347
|
};
|
|
351
348
|
|
|
352
349
|
module.exports.PARSERS = PARSERS;
|
|
353
|
-
module.exports.mkextract = mkextract;
|
|
350
|
+
module.exports.mkextract = mkextract;
|
package/tests/parse.spec.js
CHANGED
|
@@ -10,7 +10,7 @@ describe('Comment string parsing', function() {
|
|
|
10
10
|
* 0 function() {
|
|
11
11
|
* 1 // source with comments
|
|
12
12
|
* 2 }
|
|
13
|
-
*
|
|
13
|
+
*
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
function parsed(func, opts) {
|
|
@@ -39,11 +39,11 @@ describe('Comment string parsing', function() {
|
|
|
39
39
|
expect(parsed(function(){
|
|
40
40
|
/**
|
|
41
41
|
*
|
|
42
|
-
*
|
|
42
|
+
*
|
|
43
43
|
* Description first line
|
|
44
44
|
*
|
|
45
45
|
* Description second line
|
|
46
|
-
*
|
|
46
|
+
*
|
|
47
47
|
*/
|
|
48
48
|
var a;
|
|
49
49
|
})[0])
|
|
@@ -59,7 +59,7 @@ describe('Comment string parsing', function() {
|
|
|
59
59
|
|
|
60
60
|
expect(parsed(function(){
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
*
|
|
63
63
|
*/
|
|
64
64
|
var a;
|
|
65
65
|
}).length)
|
|
@@ -132,6 +132,28 @@ describe('Comment string parsing', function() {
|
|
|
132
132
|
.to.eq(0);
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
+
it('should preserve empty lines and indentation with `opts.trim = false`', function() {
|
|
136
|
+
expect(parsed(function(){
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
*
|
|
140
|
+
* Description first line
|
|
141
|
+
* second line
|
|
142
|
+
*
|
|
143
|
+
* third line
|
|
144
|
+
*/
|
|
145
|
+
var a;
|
|
146
|
+
}, {
|
|
147
|
+
trim: false
|
|
148
|
+
})[0])
|
|
149
|
+
.eql({
|
|
150
|
+
description : '\n\n\n Description first line\n second line\n\n third line\n',
|
|
151
|
+
source : '\n\n\n Description first line\n second line\n\n third line\n',
|
|
152
|
+
line : 1,
|
|
153
|
+
tags : []
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
135
157
|
it('should parse one line block with tag', function() {
|
|
136
158
|
expect(parsed(function(){
|
|
137
159
|
/** @tag */
|
|
@@ -156,7 +178,7 @@ describe('Comment string parsing', function() {
|
|
|
156
178
|
it('should parse `@tag`', function() {
|
|
157
179
|
expect(parsed(function(){
|
|
158
180
|
/**
|
|
159
|
-
*
|
|
181
|
+
*
|
|
160
182
|
* @my-tag
|
|
161
183
|
*/
|
|
162
184
|
var a;
|
|
@@ -230,14 +252,14 @@ describe('Comment string parsing', function() {
|
|
|
230
252
|
})[0])
|
|
231
253
|
.to.eql({
|
|
232
254
|
line : 1,
|
|
233
|
-
source : '@my-tag {my.type} name',
|
|
255
|
+
source : '@my-tag {my.type} name',
|
|
234
256
|
description : '',
|
|
235
257
|
tags: [{
|
|
236
258
|
tag : 'my-tag',
|
|
237
259
|
line : 2,
|
|
238
260
|
type : 'my.type',
|
|
239
261
|
name : 'name',
|
|
240
|
-
source : '@my-tag {my.type} name',
|
|
262
|
+
source : '@my-tag {my.type} name',
|
|
241
263
|
description : '',
|
|
242
264
|
optional : false
|
|
243
265
|
}]
|
|
@@ -259,7 +281,7 @@ describe('Comment string parsing', function() {
|
|
|
259
281
|
line : 2,
|
|
260
282
|
type : 'my.type',
|
|
261
283
|
name : 'name',
|
|
262
|
-
source : '@my-tag {my.type} name description',
|
|
284
|
+
source : '@my-tag {my.type} name description',
|
|
263
285
|
description : 'description',
|
|
264
286
|
optional : false
|
|
265
287
|
}]
|
|
@@ -426,7 +448,7 @@ describe('Comment string parsing', function() {
|
|
|
426
448
|
});
|
|
427
449
|
});
|
|
428
450
|
|
|
429
|
-
it('should parse
|
|
451
|
+
it('should parse optional rest names `@tag [...name] desc`', function() {
|
|
430
452
|
expect(parsed(function(){
|
|
431
453
|
/**
|
|
432
454
|
* @tag {t} [...name] desc
|
|
@@ -567,4 +589,26 @@ describe('Comment string parsing', function() {
|
|
|
567
589
|
}]
|
|
568
590
|
});
|
|
569
591
|
});
|
|
592
|
+
|
|
593
|
+
it('parses $ in description`', function() {
|
|
594
|
+
expect(parsed(function(){
|
|
595
|
+
/**
|
|
596
|
+
* @my-tag {String} name description with $ char
|
|
597
|
+
*/
|
|
598
|
+
})[0])
|
|
599
|
+
.to.eql({
|
|
600
|
+
line : 1,
|
|
601
|
+
source : '@my-tag {String} name description with $ char',
|
|
602
|
+
description : '',
|
|
603
|
+
tags: [{
|
|
604
|
+
tag : 'my-tag',
|
|
605
|
+
line : 2,
|
|
606
|
+
type : 'String',
|
|
607
|
+
name : 'name',
|
|
608
|
+
source : '@my-tag {String} name description with $ char',
|
|
609
|
+
optional : false,
|
|
610
|
+
description : 'description with $ char'
|
|
611
|
+
}]
|
|
612
|
+
});
|
|
613
|
+
});
|
|
570
614
|
});
|