comment-parser 0.2.4 → 0.4.0
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/.jshintrc +11 -0
- package/.travis.yml +8 -0
- package/CHANGELOG.md +15 -1
- package/README.md +122 -39
- package/index.js +19 -277
- package/package.json +8 -3
- package/parser.js +350 -0
- package/tests/custom-parsers.spec.js +139 -0
- package/tests/files.spec.js +1 -1
- package/tests/parse.spec.js +283 -124
- package/tests/option-raw.spec.js +0 -154
- package/tests/parse-location.spec.js +0 -190
package/.jshintrc
ADDED
package/.travis.yml
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# v0.4.0
|
|
2
|
+
- allow to preserve exact source and line numbers with `opts.trim = false`
|
|
3
|
+
|
|
4
|
+
# v0.3.1
|
|
5
|
+
- use `readable-stream` fro Node 0.8 comatibility
|
|
6
|
+
- allow to pass optional parameters to `parse.file(path [,opts], done)`
|
|
7
|
+
- allow `parse.stream` to work with Buffers in addition to strings
|
|
8
|
+
|
|
9
|
+
# v0.3.0
|
|
10
|
+
- `feature` allow to use custom parsers
|
|
11
|
+
- `feature` always include source, no `raw_value` option needed
|
|
12
|
+
- `bugfix` always provide `optional` tag property
|
|
13
|
+
- `refactor` clean up tests
|
|
14
|
+
|
|
1
15
|
# v0.2.3
|
|
2
16
|
|
|
3
17
|
- `bugfix` Accept `/** one line */` comments
|
|
@@ -28,4 +42,4 @@
|
|
|
28
42
|
|
|
29
43
|
# v0.1.0
|
|
30
44
|
|
|
31
|
-
Initial implementation
|
|
45
|
+
Initial implementation
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
comment-parser
|
|
2
|
-
|
|
1
|
+
# comment-parser
|
|
2
|
+
|
|
3
3
|
|
|
4
4
|
Generic JSDoc-like comment parser. This library is not intended to be documentation generator, but rather composite unit for it.
|
|
5
5
|
|
|
6
6
|
`npm install comment-parser`
|
|
7
7
|
|
|
8
|
-
Module provides `parse(s:String[,
|
|
8
|
+
Module provides `parse(s:String[, options:Object]):Object` function which takes `/** ... */` comment string and returns array of objects with parsed data.
|
|
9
9
|
|
|
10
10
|
It is not trying to detect relations between tags or somehow recognize their meaning. Any tag can be used, as long as it satisfies the format.
|
|
11
11
|
|
|
@@ -25,50 +25,133 @@ this would be parsed into following
|
|
|
25
25
|
|
|
26
26
|
```javascript
|
|
27
27
|
[{
|
|
28
|
-
tags: [{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
28
|
+
"tags": [{
|
|
29
|
+
"tag": "some-tag",
|
|
30
|
+
"type": "Type",
|
|
31
|
+
"name": "name",
|
|
32
|
+
"optional": false,
|
|
33
|
+
"description": "Singleline or multiline description text",
|
|
34
|
+
"line": 3,
|
|
35
|
+
"source": "@some-tag {Type} name Singleline or multiline description text"
|
|
36
|
+
}, {
|
|
37
|
+
"tag": "some-tag",
|
|
38
|
+
"type": "Type",
|
|
39
|
+
"name": "name.subname",
|
|
40
|
+
"optional": false,
|
|
41
|
+
"description": "Singleline or multiline description text",
|
|
42
|
+
"line": 4,
|
|
43
|
+
"source": "@some-tag {Type} name.subname Singleline or multiline description text"
|
|
44
|
+
}, {
|
|
45
|
+
"tag": "some-tag",
|
|
46
|
+
"type": "Type",
|
|
47
|
+
"name": "name.subname.subsubname",
|
|
48
|
+
"optional": false,
|
|
49
|
+
"description": "Singleline or\nmultiline description text",
|
|
50
|
+
"line": 5,
|
|
51
|
+
"source": "@some-tag {Type} name.subname.subsubname Singleline or\nmultiline description text"
|
|
52
|
+
}, {
|
|
53
|
+
"tag": "another-tag",
|
|
54
|
+
"name": "",
|
|
55
|
+
"optional": false,
|
|
56
|
+
"type": "",
|
|
57
|
+
"description": "",
|
|
58
|
+
"line": 7,
|
|
59
|
+
"source": "@another-tag"
|
|
60
|
+
}],
|
|
61
|
+
"line": 0,
|
|
62
|
+
"description": "Singleline or multiline description text. Line breaks are preserved.",
|
|
63
|
+
"source": "Singleline or multiline description text. Line breaks are preserved.\n\n@some-tag {Type} name Singleline or multiline description text\n@some-tag {Type} name.subname Singleline or multiline description text\n@some-tag {Type} name.subname.subsubname Singleline or\nmultiline description text\n@another-tag"
|
|
56
64
|
}]
|
|
57
65
|
```
|
|
58
66
|
|
|
59
|
-
By default dotted names like `name.subname.subsubname` will be expanded into nested sections, this can be prevented by passing `opts.dotted_names = false`.
|
|
60
|
-
|
|
61
|
-
You can also make raw line available in parsed results by passing `opts.raw_value = true`.
|
|
62
|
-
|
|
63
67
|
Invalid comment blocks are skipped. Comments starting with `/*` and `/***` are considered not valid.
|
|
64
68
|
|
|
65
69
|
Also you can parse entire file with `parse.file('path/to/file', callback)` or acquire an instance of [Transform](http://nodejs.org/api/stream.html#stream_class_stream_transform) stream with `parse.stream()`.
|
|
66
70
|
|
|
67
|
-
Happy coding :)
|
|
68
71
|
|
|
72
|
+
### Options
|
|
73
|
+
|
|
74
|
+
#### dotted_names `true`
|
|
75
|
+
|
|
76
|
+
Tells parser to expand dotted names like `name.subname.subsubname` into nested sections
|
|
77
|
+
|
|
78
|
+
#### trim `true`
|
|
79
|
+
|
|
80
|
+
Makes parser to trim white spaces, set it to `false` to preserve exact source and line numbers
|
|
81
|
+
|
|
82
|
+
#### parsers, `[PARSERS.{parse_tag, parse_type, parse_name, parse_description}]`
|
|
83
|
+
|
|
84
|
+
Array of alternative parsers (read below).
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
## Custom parsers
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
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}`.
|
|
91
|
+
|
|
92
|
+
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.
|
|
93
|
+
|
|
94
|
+
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:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
/**
|
|
98
|
+
* Source to be parsed below
|
|
99
|
+
* @tag {type} name Description
|
|
100
|
+
*/
|
|
101
|
+
parse(source, {parsers: [
|
|
102
|
+
// takes entire string
|
|
103
|
+
function parse_tag(str, data) {
|
|
104
|
+
return {source: ' @tag', data: {tag: 'tag'}};
|
|
105
|
+
},
|
|
106
|
+
// parser throwing exception
|
|
107
|
+
function check_tag(str, data) {
|
|
108
|
+
if (allowed_tags.indexOf(data.tag) === -1) {
|
|
109
|
+
throw new Error('Unrecognized tag "' + data.tag + '"');
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
// takes the rest of the string after ' @tag''
|
|
113
|
+
function parse_name1(str, data) {
|
|
114
|
+
return {source: ' name', data: {name: 'name1'}};
|
|
115
|
+
},
|
|
116
|
+
// alternative name parser
|
|
117
|
+
function parse_name2(str, data) {
|
|
118
|
+
return {source: ' name', data: {name: 'name2'}};
|
|
119
|
+
}
|
|
120
|
+
]});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
This would produce following:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
[{
|
|
127
|
+
"tags": [{
|
|
128
|
+
"tag": "tag",
|
|
129
|
+
"errors": [
|
|
130
|
+
"check_tag: Unrecognized tag \\"tag\\""
|
|
131
|
+
],
|
|
132
|
+
"name": "name2",
|
|
133
|
+
"optional": false,
|
|
134
|
+
"type": "",
|
|
135
|
+
"description": "",
|
|
136
|
+
"line": 2,
|
|
137
|
+
"source": "@tag {type} name Description"
|
|
138
|
+
}],
|
|
139
|
+
"line": 0,
|
|
140
|
+
"description": "Source to be parsed below",
|
|
141
|
+
"source": "Source to be parsed below\n@tag {type} name Description"
|
|
142
|
+
}]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Packaging
|
|
146
|
+
|
|
147
|
+
`comment-parser` is CommonJS module and was primarely designed to be used with Node. Module `index.js` includes stream and file functionality. Use prser-only module in browser `comment-parser/parse.js`
|
|
148
|
+
|
|
149
|
+
## Contributors
|
|
69
150
|
|
|
70
|
-
Contributors
|
|
71
|
-
============
|
|
72
151
|
|
|
73
152
|
- [Sergii Iavorskyi](https://github.com/yavorskiy)
|
|
74
|
-
- [Alexej Yaroshevich](https://github.com/zxqfox)
|
|
153
|
+
- [Alexej Yaroshevich](https://github.com/zxqfox)
|
|
154
|
+
- [Jordan Harband](https://github.com/ljharb)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
Happy coding :)
|
package/index.js
CHANGED
|
@@ -1,250 +1,20 @@
|
|
|
1
1
|
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
2
4
|
var fs = require('fs');
|
|
3
|
-
var stream = require('stream');
|
|
5
|
+
var stream = require('readable-stream');
|
|
4
6
|
var util = require('util');
|
|
5
7
|
|
|
6
|
-
var
|
|
7
|
-
var RE_COMMENT_LINE = /^\s*\*(?:\s|$)/m;
|
|
8
|
-
var RE_COMMENT_END = /^\s*\*\/\s*$/m;
|
|
9
|
-
var RE_COMMENT_1LINE = /^\s*\/\*\*\s*(.*)\s*\*\/\s*$/;
|
|
10
|
-
var RE_SPACE = /\s/;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* analogue of str.match(/@(\S+)(?:\s+\{([^\}]+)\})?(?:\s+(\S+))?(?:\s+([^$]+))?/);
|
|
14
|
-
* @param {string} str raw jsdoc string
|
|
15
|
-
* @returns {object} parsed tag node
|
|
16
|
-
*/
|
|
17
|
-
function parse_tag_line(str) {
|
|
18
|
-
if (typeof str !== 'string') { return false; }
|
|
19
|
-
|
|
20
|
-
if (str[0] !== '@') { return false; }
|
|
21
|
-
|
|
22
|
-
var pos = 1;
|
|
23
|
-
var l = str.length;
|
|
24
|
-
var error = null;
|
|
25
|
-
var new_line = false;
|
|
26
|
-
var res = {
|
|
27
|
-
tag : _tag(),
|
|
28
|
-
type : !new_line && _type() || '',
|
|
29
|
-
name : !new_line && _name() || '',
|
|
30
|
-
description : _rest() || ''
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
if (error) {
|
|
34
|
-
res.error = error;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return res;
|
|
38
|
-
|
|
39
|
-
function _skipws() {
|
|
40
|
-
var prev_pos = pos;
|
|
41
|
-
while (pos < l && RE_SPACE.test(str[pos])) {
|
|
42
|
-
new_line = new_line || str[pos] === '\n';
|
|
43
|
-
pos++;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function _tag() { // @(\S+)
|
|
47
|
-
var sp = str.search(RE_SPACE, pos);
|
|
48
|
-
sp = sp < 0 ? l : sp;
|
|
49
|
-
var res = str.substr(pos, sp - pos);
|
|
50
|
-
pos = sp;
|
|
51
|
-
return res;
|
|
52
|
-
}
|
|
53
|
-
function _type() { // (?:\s+\{([^\}]+)\})?
|
|
54
|
-
_skipws();
|
|
55
|
-
if (str[pos] !== '{') { return ''; }
|
|
56
|
-
var ch;
|
|
57
|
-
var res = '';
|
|
58
|
-
var curlies = 0;
|
|
59
|
-
while (pos < l) {
|
|
60
|
-
ch = str[pos];
|
|
61
|
-
curlies += ch === '{' ? 1 : ch === '}' ? -1 : 0;
|
|
62
|
-
res += ch;
|
|
63
|
-
pos ++;
|
|
64
|
-
if (!curlies) {
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (curlies !== 0) {
|
|
69
|
-
// throw new Error('Unpaired curly in type doc');
|
|
70
|
-
error = 'Unpaired curly in type doc';
|
|
71
|
-
pos -= res.length;
|
|
72
|
-
return '';
|
|
73
|
-
}
|
|
74
|
-
return res.substr(1, res.length - 2);
|
|
75
|
-
}
|
|
76
|
-
function _name() { // (?:\s+(\S+))?
|
|
77
|
-
if (error) { return ''; }
|
|
78
|
-
_skipws();
|
|
79
|
-
var ch;
|
|
80
|
-
var res = '';
|
|
81
|
-
var brackets = 0;
|
|
82
|
-
var re = /\s/;
|
|
83
|
-
while (pos < l) {
|
|
84
|
-
ch = str[pos];
|
|
85
|
-
brackets += ch === '[' ? 1 : ch === ']' ? -1 : 0;
|
|
86
|
-
res += ch;
|
|
87
|
-
pos ++;
|
|
88
|
-
if (brackets === 0 && re.test(str[pos])) {
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (brackets) {
|
|
93
|
-
// throw new Error('Unpaired curly in type doc');
|
|
94
|
-
error = 'Unpaired brackets in type doc';
|
|
95
|
-
pos -= res.length;
|
|
96
|
-
return '';
|
|
97
|
-
}
|
|
98
|
-
return res;
|
|
99
|
-
}
|
|
100
|
-
function _rest() { // (?:\s+([^$]+))?
|
|
101
|
-
_skipws();
|
|
102
|
-
return str.substr(pos);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
8
|
+
var parse = require('./parser.js');
|
|
105
9
|
|
|
106
|
-
|
|
107
|
-
source = source
|
|
108
|
-
.reduce(function(sections, line) {
|
|
109
|
-
if (line.value === '' && line.line === base_line_number) return sections;
|
|
110
|
-
if (line.value.match(/^@(\w+)/)) { sections.push([]); }
|
|
111
|
-
var section = sections[sections.length - 1];
|
|
112
|
-
section.line = 'line' in section ? section.line : line.line;
|
|
113
|
-
section.push(line.value);
|
|
114
|
-
return sections;
|
|
115
|
-
}, [[]])
|
|
116
|
-
.map(function(section) {
|
|
117
|
-
return {value: section.length ? section.join('\n').trim() : null, line: section.line};
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
var description = source.shift();
|
|
121
|
-
|
|
122
|
-
var tags = source.reduce(function(tags, tag) {
|
|
123
|
-
var tag_node = parse_tag_line(tag.value);
|
|
124
|
-
if (!tag_node) { return tags; }
|
|
125
|
-
|
|
126
|
-
tag_node.line = Number(tag.line);
|
|
127
|
-
if (opts.raw_value) {
|
|
128
|
-
tag_node.value = tag.value;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// used for split results below
|
|
132
|
-
var parts;
|
|
133
|
-
|
|
134
|
-
// parsing optional and default value if exists
|
|
135
|
-
// probably if should be hidden with option or moved out to some jsdoc standard
|
|
136
|
-
if (tag_node.name[0] === '[' && tag_node.name[tag_node.name.length - 1] === ']') {
|
|
137
|
-
tag_node.optional = true;
|
|
138
|
-
tag_node.name = tag_node.name.substr(1, tag_node.name.length - 2);
|
|
139
|
-
|
|
140
|
-
// default value here
|
|
141
|
-
if (tag_node.name.indexOf('=') !== -1) {
|
|
142
|
-
parts = tag_node.name.split('=');
|
|
143
|
-
tag_node.name = parts[0];
|
|
144
|
-
tag_node.default = parts[1].replace(/^(["'])(.+)(\1)$/, '$2');
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// hidden with `dotted_names` parsing of `obj.value` naming standard
|
|
149
|
-
if (opts.dotted_names && tag_node.name.indexOf('.') !== -1) {
|
|
150
|
-
var parent_name;
|
|
151
|
-
var parent_tag;
|
|
152
|
-
var parent_tags = tags;
|
|
153
|
-
parts = tag_node.name.split('.');
|
|
154
|
-
|
|
155
|
-
while (parts.length > 1) {
|
|
156
|
-
parent_name = parts.shift();
|
|
157
|
-
parent_tag = _find(parent_tags, {
|
|
158
|
-
tag : tag_node.tag,
|
|
159
|
-
name : parent_name
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
if (!parent_tag) {
|
|
163
|
-
parent_tag = {
|
|
164
|
-
tag : tag_node.tag,
|
|
165
|
-
line : Number(tag_node.line),
|
|
166
|
-
name : parent_name,
|
|
167
|
-
type : '',
|
|
168
|
-
description : ''
|
|
169
|
-
};
|
|
170
|
-
parent_tags.push(parent_tag);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
parent_tag.tags = parent_tag.tags || [];
|
|
174
|
-
parent_tags = parent_tag.tags;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
tag_node.name = parts[0];
|
|
178
|
-
parent_tags.push(tag_node);
|
|
179
|
-
return tags;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return tags.concat(tag_node);
|
|
183
|
-
}, []);
|
|
184
|
-
|
|
185
|
-
return {
|
|
186
|
-
tags : tags,
|
|
187
|
-
line : Number(description.line || 0),
|
|
188
|
-
description : description.value || ''
|
|
189
|
-
};
|
|
190
|
-
}
|
|
10
|
+
module.exports = parse;
|
|
191
11
|
|
|
192
|
-
|
|
193
|
-
var chunk = null;
|
|
194
|
-
var line_number = 0;
|
|
195
|
-
var base_line_number = 0;
|
|
196
|
-
|
|
197
|
-
return function extract(line) {
|
|
198
|
-
line_number += 1;
|
|
199
|
-
|
|
200
|
-
// if oneliner
|
|
201
|
-
// then parse it immediately
|
|
202
|
-
if (!chunk && line.match(RE_COMMENT_1LINE)) {
|
|
203
|
-
// console.log('line (1)', line, line_number);
|
|
204
|
-
// console.log(' clean:', line.replace(RE_COMMENT_1LINE, '$1'));
|
|
205
|
-
return parse_chunk([{value: line.replace(RE_COMMENT_1LINE, '$1'), line: line_number - 1}], line_number - 1, opts);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// if start of comment
|
|
209
|
-
// then init the chunk
|
|
210
|
-
if (line.match(RE_COMMENT_START)) {
|
|
211
|
-
// console.log('line (1)', line);
|
|
212
|
-
// console.log(' clean:', line.replace(RE_COMMENT_START, ''));
|
|
213
|
-
base_line_number = line_number - 1;
|
|
214
|
-
chunk = [{value: line.replace(RE_COMMENT_START, ''), line: line_number - 1}];
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// if comment line and chunk started
|
|
219
|
-
// then append
|
|
220
|
-
if (chunk && line.match(RE_COMMENT_LINE)) {
|
|
221
|
-
// console.log('line (2)', line);
|
|
222
|
-
// console.log(' clean:', line.replace(RE_COMMENT_LINE, ''));
|
|
223
|
-
chunk.push({value: line.replace(RE_COMMENT_LINE, ''), line: line_number - 1});
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// if comment end and chunk started
|
|
228
|
-
// then parse the chunk and push
|
|
229
|
-
if (chunk && line.match(RE_COMMENT_END)) {
|
|
230
|
-
// console.log('line (3)', line);
|
|
231
|
-
// console.log(' clean:', line.replace(RE_COMMENT_END, ''));
|
|
232
|
-
chunk.push({value: line.replace(RE_COMMENT_END, ''), line: line_number - 1});
|
|
233
|
-
return parse_chunk(chunk, base_line_number, opts);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// if non-comment line
|
|
237
|
-
// then reset the chunk
|
|
238
|
-
chunk = null;
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/* ------- Transform strean ------- */
|
|
12
|
+
/* ------- Transform stream ------- */
|
|
243
13
|
|
|
244
14
|
function Parser(opts) {
|
|
245
15
|
opts = opts || {};
|
|
246
16
|
stream.Transform.call(this, {objectMode: true});
|
|
247
|
-
this._extract = mkextract(opts);
|
|
17
|
+
this._extract = parse.mkextract(opts);
|
|
248
18
|
}
|
|
249
19
|
|
|
250
20
|
util.inherits(Parser, stream.Transform);
|
|
@@ -252,7 +22,7 @@ util.inherits(Parser, stream.Transform);
|
|
|
252
22
|
Parser.prototype._transform = function transform(data, encoding, done) {
|
|
253
23
|
|
|
254
24
|
var block;
|
|
255
|
-
var lines = data.split(/\n/);
|
|
25
|
+
var lines = data.toString().split(/\n/);
|
|
256
26
|
|
|
257
27
|
while (lines.length) {
|
|
258
28
|
block = this._extract(lines.shift());
|
|
@@ -264,34 +34,25 @@ Parser.prototype._transform = function transform(data, encoding, done) {
|
|
|
264
34
|
done();
|
|
265
35
|
};
|
|
266
36
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
module.exports = function parse(source, opts) {
|
|
270
|
-
opts = opts || {};
|
|
271
|
-
|
|
272
|
-
var block;
|
|
273
|
-
var blocks = [];
|
|
274
|
-
var extract = mkextract(opts);
|
|
275
|
-
var lines = source.split(/\n/);
|
|
276
|
-
|
|
277
|
-
while (lines.length) {
|
|
278
|
-
block = extract(lines.shift());
|
|
279
|
-
if (block) {
|
|
280
|
-
blocks.push(block);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return blocks;
|
|
37
|
+
module.exports.stream = function stream(opts) {
|
|
38
|
+
return new Parser(opts);
|
|
285
39
|
};
|
|
286
40
|
|
|
41
|
+
/* ------- File parser ------- */
|
|
42
|
+
|
|
287
43
|
module.exports.file = function file(file_path, done) {
|
|
288
44
|
|
|
45
|
+
var opts = {};
|
|
289
46
|
var collected = [];
|
|
290
47
|
|
|
48
|
+
if (arguments.length === 3) {
|
|
49
|
+
opts = done;
|
|
50
|
+
done = arguments[2];
|
|
51
|
+
}
|
|
52
|
+
|
|
291
53
|
return fs.createReadStream(file_path, {encoding: 'utf8'})
|
|
292
54
|
.on('error', done)
|
|
293
|
-
|
|
294
|
-
.pipe(new Parser())
|
|
55
|
+
.pipe(new Parser(opts))
|
|
295
56
|
.on('error', done)
|
|
296
57
|
.on('data', function(data) {
|
|
297
58
|
collected.push(data);
|
|
@@ -301,22 +62,3 @@ module.exports.file = function file(file_path, done) {
|
|
|
301
62
|
});
|
|
302
63
|
};
|
|
303
64
|
|
|
304
|
-
module.exports.stream = function stream(opts) {
|
|
305
|
-
return new Parser(opts);
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
function _find(list, filter) {
|
|
309
|
-
var i, l, k, yes, item;
|
|
310
|
-
for (i = 0, l = list.length; i < l; i++) {
|
|
311
|
-
item = list[i];
|
|
312
|
-
yes = true;
|
|
313
|
-
for (k in filter) {
|
|
314
|
-
if (filter.hasOwnProperty(k)) {
|
|
315
|
-
yes = yes && filter[k] === list[i][k];
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
if (yes) {
|
|
319
|
-
return item;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comment-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Generic JSDoc-like comment parser. ",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
7
7
|
"test": "tests"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
+
"readable-stream": "^2.0.4"
|
|
10
11
|
},
|
|
11
12
|
"devDependencies": {
|
|
13
|
+
"chai": "~1.9.0",
|
|
14
|
+
"jshint": "^2.5.10",
|
|
15
|
+
"jshint-stylish": "^1.0.0",
|
|
12
16
|
"mocha": "~1.17.1",
|
|
13
|
-
"
|
|
17
|
+
"nodemon": "^1.2.1"
|
|
14
18
|
},
|
|
15
19
|
"scripts": {
|
|
16
|
-
"test": "mocha tests/*"
|
|
20
|
+
"test": "jshint --reporter node_modules/jshint-stylish/stylish.js index.js && mocha tests/*",
|
|
21
|
+
"watch": "nodemon -q -w index.js -w parser.js -w tests/ -x npm test"
|
|
17
22
|
},
|
|
18
23
|
"repository": {
|
|
19
24
|
"type": "git",
|