comment-parser 0.2.4 → 0.3.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/README.md +89 -30
- package/index.js +232 -150
- package/package.json +8 -5
- package/tests/custom-parsers.spec.js +139 -0
- package/tests/parse.spec.js +261 -124
- package/tests/option-raw.spec.js +0 -154
- package/tests/parse-location.spec.js +0 -190
package/.jshintrc
ADDED
package/README.md
CHANGED
|
@@ -25,45 +25,104 @@ 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
67
|
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
68
|
|
|
61
|
-
You can also make raw line available in parsed results by passing `opts.raw_value = true`.
|
|
62
|
-
|
|
63
69
|
Invalid comment blocks are skipped. Comments starting with `/*` and `/***` are considered not valid.
|
|
64
70
|
|
|
65
71
|
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
72
|
|
|
73
|
+
Custom parsers
|
|
74
|
+
==============
|
|
75
|
+
|
|
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
|
+
|
|
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
|
+
|
|
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:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
/**
|
|
84
|
+
* Source to be parsed below
|
|
85
|
+
* @tag {type} name Description
|
|
86
|
+
*/
|
|
87
|
+
parse(source, {parsers: [
|
|
88
|
+
// takes entire string
|
|
89
|
+
function parse_tag(str, data) {
|
|
90
|
+
return {source: ' @tag', data: {tag: 'tag'}};
|
|
91
|
+
},
|
|
92
|
+
// parser throwing exception
|
|
93
|
+
function check_tag(str, data) {
|
|
94
|
+
if (allowed_tags.indexOf(data.tag) === -1) {
|
|
95
|
+
throw new Error('Unrecognized tag "' + data.tag + '"');
|
|
96
|
+
}
|
|
97
|
+
// takes the rest of the string after ' @tag''
|
|
98
|
+
function parse_name1(str, data) {
|
|
99
|
+
return {source: ' name', data: {name: 'name'}};
|
|
100
|
+
},
|
|
101
|
+
// alternative name parser
|
|
102
|
+
function parse_name2(str, data) {
|
|
103
|
+
return {source: ' name', data: {name: 'name'}};
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This would produce following:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
[{
|
|
111
|
+
"tags": [{
|
|
112
|
+
"tag": "tag",
|
|
113
|
+
"type": "type",
|
|
114
|
+
"name": "name",
|
|
115
|
+
"optional": false,
|
|
116
|
+
"description": "Description",
|
|
117
|
+
"line": 2,
|
|
118
|
+
"source": "@tag {type} name Description"
|
|
119
|
+
}],
|
|
120
|
+
"line": 0,
|
|
121
|
+
"description": "Source to be parsed below",
|
|
122
|
+
"source": "Source to be parsed below\n@tag {type} name Description"
|
|
123
|
+
}]
|
|
124
|
+
```
|
|
125
|
+
|
|
67
126
|
Happy coding :)
|
|
68
127
|
|
|
69
128
|
|
package/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
2
4
|
var fs = require('fs');
|
|
3
5
|
var stream = require('stream');
|
|
4
6
|
var util = require('util');
|
|
@@ -7,154 +9,235 @@ var RE_COMMENT_START = /^\s*\/\*\*\s*$/m;
|
|
|
7
9
|
var RE_COMMENT_LINE = /^\s*\*(?:\s|$)/m;
|
|
8
10
|
var RE_COMMENT_END = /^\s*\*\/\s*$/m;
|
|
9
11
|
var RE_COMMENT_1LINE = /^\s*\/\*\*\s*(.*)\s*\*\/\s*$/;
|
|
10
|
-
var RE_SPACE = /\s/;
|
|
11
12
|
|
|
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
|
-
};
|
|
13
|
+
/* ------- util functions ------- */
|
|
32
14
|
|
|
33
|
-
|
|
34
|
-
|
|
15
|
+
function merge(/* ...objects */) {
|
|
16
|
+
var k, obj, res = {}, objs = Array.prototype.slice.call(arguments);
|
|
17
|
+
while (objs.length) {
|
|
18
|
+
obj = objs.shift();
|
|
19
|
+
for (k in obj) { if (obj.hasOwnProperty(k)) {
|
|
20
|
+
res[k] = obj[k];
|
|
21
|
+
}}
|
|
35
22
|
}
|
|
36
|
-
|
|
37
23
|
return res;
|
|
24
|
+
}
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
26
|
+
function find(list, filter) {
|
|
27
|
+
var k, i = list.length, matchs = true;
|
|
28
|
+
while (i--) {
|
|
29
|
+
for (k in filter) { if (filter.hasOwnProperty(k)) {
|
|
30
|
+
matchs = (filter[k] === list[i][k]) && matchs;
|
|
31
|
+
}}
|
|
32
|
+
if (matchs) { return list[i]; }
|
|
45
33
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function skipws(str) {
|
|
38
|
+
var i = 0;
|
|
39
|
+
do {
|
|
40
|
+
if (str[i] !== ' ') { return i; }
|
|
41
|
+
} while (++i < str.length);
|
|
42
|
+
return i;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ------- default parsers ------- */
|
|
46
|
+
|
|
47
|
+
var PARSERS = {};
|
|
48
|
+
|
|
49
|
+
PARSERS.parse_tag = function parse_tag(str) {
|
|
50
|
+
var result = str.match(/^\s*@(\S+)/);
|
|
51
|
+
|
|
52
|
+
if (!result) { throw new Error('Invalid `@tag`, missing @ symbol'); }
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
source : result[0],
|
|
56
|
+
data : {tag: result[1]}
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
PARSERS.parse_type = function parse_type(str, data) {
|
|
61
|
+
if (data.errors && data.errors.length) { return null; }
|
|
62
|
+
|
|
63
|
+
var pos = skipws(str);
|
|
64
|
+
var res = '';
|
|
65
|
+
var curlies = 0;
|
|
66
|
+
|
|
67
|
+
if (str[pos] !== '{') { return null; }
|
|
68
|
+
|
|
69
|
+
while (pos < str.length) {
|
|
70
|
+
curlies += (str[pos] === '{' ? 1 : (str[pos] === '}' ? -1 : 0));
|
|
71
|
+
res += str[pos];
|
|
72
|
+
pos ++;
|
|
73
|
+
if (curlies === 0) { break; }
|
|
52
74
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
return res.substr(1, res.length - 2);
|
|
75
|
+
|
|
76
|
+
if (curlies !== 0) { throw new Error('Invalid `{type}`, unpaired curlies'); }
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
source : str.slice(0, pos),
|
|
80
|
+
data : {type: res.slice(1, -1)}
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
PARSERS.parse_name = function parse_name(str, data) {
|
|
85
|
+
if (data.errors && data.errors.length) { return null; }
|
|
86
|
+
|
|
87
|
+
var pos = skipws(str);
|
|
88
|
+
var name = '';
|
|
89
|
+
var brackets = 0;
|
|
90
|
+
|
|
91
|
+
while (pos < str.length) {
|
|
92
|
+
brackets += (str[pos] === '[' ? 1 : (str[pos] === ']' ? -1 : 0));
|
|
93
|
+
name += str[pos];
|
|
94
|
+
pos ++;
|
|
95
|
+
if (brackets === 0 && /\s/.test(str[pos])) { break; }
|
|
75
96
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
+
if (brackets !== 0) { throw new Error('Invalid `name`, unpaired brackets'); }
|
|
99
|
+
|
|
100
|
+
var res = {name: name, optional: false};
|
|
101
|
+
|
|
102
|
+
if (name[0] === '[' && name[name.length - 1] === ']') {
|
|
103
|
+
res.optional = true;
|
|
104
|
+
name = name.slice(1, -1);
|
|
105
|
+
|
|
106
|
+
if (name.indexOf('=') !== -1) {
|
|
107
|
+
var parts = name.split('=');
|
|
108
|
+
name = parts[0];
|
|
109
|
+
res.default = parts[1].replace(/^(["'])(.+)(\1)$/, '$2');
|
|
97
110
|
}
|
|
98
|
-
return res;
|
|
99
111
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
112
|
+
|
|
113
|
+
res.name = name;
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
source : str.slice(0, pos),
|
|
117
|
+
data : res
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
PARSERS.parse_description = function parse_description(str, data) {
|
|
122
|
+
if (data.errors && data.errors.length) { return null; }
|
|
123
|
+
|
|
124
|
+
var result = str.match(/^\s+([^$]+)?/);
|
|
125
|
+
|
|
126
|
+
if (result) {
|
|
127
|
+
return {
|
|
128
|
+
source : result[0],
|
|
129
|
+
data : {description: result[1] === undefined ? '' : result[1]}
|
|
130
|
+
};
|
|
103
131
|
}
|
|
132
|
+
|
|
133
|
+
return null;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/* ------- parsing ------- */
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Parses "@tag {type} name description"
|
|
140
|
+
* @param {string} str Raw doc string
|
|
141
|
+
* @param {Array[function]} parsers Array of parsers to be applied to the source
|
|
142
|
+
* @returns {object} parsed tag node
|
|
143
|
+
*/
|
|
144
|
+
function parse_tag(str, parsers) {
|
|
145
|
+
if (typeof str !== 'string' || str[0] !== '@') { return null; }
|
|
146
|
+
|
|
147
|
+
var data = parsers.reduce(function(state, parser) {
|
|
148
|
+
var result;
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
result = parser(state.source, merge({}, state.data));
|
|
152
|
+
// console.log('----------------');
|
|
153
|
+
// console.log(parser.name, ':', result);
|
|
154
|
+
} catch (err) {
|
|
155
|
+
// console.warn('Parser "%s" failed: %s', parser.name, err.message);
|
|
156
|
+
state.data.errors = (state.data.errors || [])
|
|
157
|
+
.concat(parser.name + ': ' + err.message);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (result) {
|
|
161
|
+
state.source = state.source.slice(result.source.length);
|
|
162
|
+
state.data = merge(state.data, result.data);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return state;
|
|
166
|
+
}, {
|
|
167
|
+
source : str,
|
|
168
|
+
data : {}
|
|
169
|
+
}).data;
|
|
170
|
+
|
|
171
|
+
data.optional = !!data.optional;
|
|
172
|
+
data.type = data.type === undefined ? '' : data.type;
|
|
173
|
+
data.name = data.name === undefined ? '' : data.name;
|
|
174
|
+
data.description = data.description === undefined ? '' : data.description;
|
|
175
|
+
|
|
176
|
+
return data;
|
|
104
177
|
}
|
|
105
178
|
|
|
106
|
-
|
|
179
|
+
/**
|
|
180
|
+
* Parses comment block (array of String lines)
|
|
181
|
+
*/
|
|
182
|
+
function parse_block(source, opts) {
|
|
183
|
+
|
|
184
|
+
var source_str = source
|
|
185
|
+
.map(function(line) { return line.source; })
|
|
186
|
+
.join('\n')
|
|
187
|
+
.trim();
|
|
188
|
+
|
|
189
|
+
var start = source[0].number;
|
|
190
|
+
|
|
191
|
+
// merge source lines into tags
|
|
192
|
+
// we assume tag starts with "@"
|
|
107
193
|
source = source
|
|
108
|
-
.reduce(function(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
194
|
+
.reduce(function(tags, line) {
|
|
195
|
+
line.source = line.source.trim();
|
|
196
|
+
|
|
197
|
+
if (line.source.match(/^@(\w+)/)) {
|
|
198
|
+
tags.push({source: [line.source], line: line.number});
|
|
199
|
+
} else {
|
|
200
|
+
var tag = tags[tags.length - 1];
|
|
201
|
+
tag.source.push(line.source);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return tags;
|
|
205
|
+
}, [{source: []}])
|
|
206
|
+
.map(function(tag) {
|
|
207
|
+
tag.source = tag.source.join('\n').trim();
|
|
208
|
+
return tag;
|
|
118
209
|
});
|
|
119
210
|
|
|
211
|
+
// Block description
|
|
120
212
|
var description = source.shift();
|
|
121
213
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
tag_node.line = Number(tag.line);
|
|
127
|
-
if (opts.raw_value) {
|
|
128
|
-
tag_node.value = tag.value;
|
|
129
|
-
}
|
|
214
|
+
// skip if no descriptions and no tags
|
|
215
|
+
if (description.source === '' && source.length === 0) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
130
218
|
|
|
131
|
-
|
|
132
|
-
var
|
|
219
|
+
var tags = source.reduce(function(tags, tag) {
|
|
220
|
+
var tag_node = parse_tag(tag.source, opts.parsers || [
|
|
221
|
+
PARSERS.parse_tag,
|
|
222
|
+
PARSERS.parse_type,
|
|
223
|
+
PARSERS.parse_name,
|
|
224
|
+
PARSERS.parse_description
|
|
225
|
+
]);
|
|
133
226
|
|
|
134
|
-
|
|
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);
|
|
227
|
+
if (!tag_node) { return tags; }
|
|
139
228
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
parts = tag_node.name.split('=');
|
|
143
|
-
tag_node.name = parts[0];
|
|
144
|
-
tag_node.default = parts[1].replace(/^(["'])(.+)(\1)$/, '$2');
|
|
145
|
-
}
|
|
146
|
-
}
|
|
229
|
+
tag_node.line = tag.line;
|
|
230
|
+
tag_node.source = tag.source;
|
|
147
231
|
|
|
148
|
-
// hidden with `dotted_names` parsing of `obj.value` naming standard
|
|
149
232
|
if (opts.dotted_names && tag_node.name.indexOf('.') !== -1) {
|
|
150
233
|
var parent_name;
|
|
151
234
|
var parent_tag;
|
|
152
235
|
var parent_tags = tags;
|
|
153
|
-
parts = tag_node.name.split('.');
|
|
236
|
+
var parts = tag_node.name.split('.');
|
|
154
237
|
|
|
155
238
|
while (parts.length > 1) {
|
|
156
239
|
parent_name = parts.shift();
|
|
157
|
-
parent_tag =
|
|
240
|
+
parent_tag = find(parent_tags, {
|
|
158
241
|
tag : tag_node.tag,
|
|
159
242
|
name : parent_name
|
|
160
243
|
});
|
|
@@ -181,37 +264,50 @@ function parse_chunk(source, base_line_number, opts) {
|
|
|
181
264
|
|
|
182
265
|
return tags.concat(tag_node);
|
|
183
266
|
}, []);
|
|
184
|
-
|
|
267
|
+
|
|
268
|
+
// console.log('-----------');
|
|
269
|
+
// console.log(description, tags);
|
|
270
|
+
|
|
185
271
|
return {
|
|
186
272
|
tags : tags,
|
|
187
|
-
line :
|
|
188
|
-
description : description.
|
|
273
|
+
line : start,
|
|
274
|
+
description : description.source,
|
|
275
|
+
source : source_str
|
|
189
276
|
};
|
|
190
277
|
}
|
|
191
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Produces `extract` function with internal state initialized
|
|
281
|
+
*/
|
|
192
282
|
function mkextract(opts) {
|
|
283
|
+
|
|
193
284
|
var chunk = null;
|
|
194
|
-
var
|
|
195
|
-
var base_line_number = 0;
|
|
285
|
+
var number = 0;
|
|
196
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Cumulatively reading lines until they make one comment block
|
|
289
|
+
* Returns block object or null.
|
|
290
|
+
*/
|
|
197
291
|
return function extract(line) {
|
|
198
|
-
line_number += 1;
|
|
199
292
|
|
|
200
293
|
// if oneliner
|
|
201
294
|
// then parse it immediately
|
|
202
|
-
if (
|
|
203
|
-
// console.log('line (1)', line
|
|
295
|
+
if (line.match(RE_COMMENT_1LINE)) {
|
|
296
|
+
// console.log('line (1)', line);
|
|
204
297
|
// console.log(' clean:', line.replace(RE_COMMENT_1LINE, '$1'));
|
|
205
|
-
return
|
|
298
|
+
return parse_block([{
|
|
299
|
+
source: line.replace(RE_COMMENT_1LINE, '$1'),
|
|
300
|
+
number: number}], opts);
|
|
206
301
|
}
|
|
207
302
|
|
|
303
|
+
number += 1;
|
|
304
|
+
|
|
208
305
|
// if start of comment
|
|
209
306
|
// then init the chunk
|
|
210
307
|
if (line.match(RE_COMMENT_START)) {
|
|
211
308
|
// console.log('line (1)', line);
|
|
212
309
|
// console.log(' clean:', line.replace(RE_COMMENT_START, ''));
|
|
213
|
-
|
|
214
|
-
chunk = [{value: line.replace(RE_COMMENT_START, ''), line: line_number - 1}];
|
|
310
|
+
chunk = [{source: line.replace(RE_COMMENT_START, ''), number: number - 1}];
|
|
215
311
|
return null;
|
|
216
312
|
}
|
|
217
313
|
|
|
@@ -220,7 +316,7 @@ function mkextract(opts) {
|
|
|
220
316
|
if (chunk && line.match(RE_COMMENT_LINE)) {
|
|
221
317
|
// console.log('line (2)', line);
|
|
222
318
|
// console.log(' clean:', line.replace(RE_COMMENT_LINE, ''));
|
|
223
|
-
chunk.push({
|
|
319
|
+
chunk.push({source: line.replace(RE_COMMENT_LINE, ''), number: number - 1});
|
|
224
320
|
return null;
|
|
225
321
|
}
|
|
226
322
|
|
|
@@ -229,8 +325,8 @@ function mkextract(opts) {
|
|
|
229
325
|
if (chunk && line.match(RE_COMMENT_END)) {
|
|
230
326
|
// console.log('line (3)', line);
|
|
231
327
|
// console.log(' clean:', line.replace(RE_COMMENT_END, ''));
|
|
232
|
-
chunk.push({
|
|
233
|
-
return
|
|
328
|
+
chunk.push({source: line.replace(RE_COMMENT_END, ''), number: number - 1});
|
|
329
|
+
return parse_block(chunk, opts);
|
|
234
330
|
}
|
|
235
331
|
|
|
236
332
|
// if non-comment line
|
|
@@ -239,7 +335,7 @@ function mkextract(opts) {
|
|
|
239
335
|
};
|
|
240
336
|
}
|
|
241
337
|
|
|
242
|
-
/* ------- Transform
|
|
338
|
+
/* ------- Transform stream ------- */
|
|
243
339
|
|
|
244
340
|
function Parser(opts) {
|
|
245
341
|
opts = opts || {};
|
|
@@ -284,6 +380,8 @@ module.exports = function parse(source, opts) {
|
|
|
284
380
|
return blocks;
|
|
285
381
|
};
|
|
286
382
|
|
|
383
|
+
module.exports.PARSERS = PARSERS;
|
|
384
|
+
|
|
287
385
|
module.exports.file = function file(file_path, done) {
|
|
288
386
|
|
|
289
387
|
var collected = [];
|
|
@@ -304,19 +402,3 @@ module.exports.file = function file(file_path, done) {
|
|
|
304
402
|
module.exports.stream = function stream(opts) {
|
|
305
403
|
return new Parser(opts);
|
|
306
404
|
};
|
|
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,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comment-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Generic JSDoc-like comment parser. ",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
7
7
|
"test": "tests"
|
|
8
8
|
},
|
|
9
|
-
"dependencies": {
|
|
10
|
-
},
|
|
9
|
+
"dependencies": {},
|
|
11
10
|
"devDependencies": {
|
|
11
|
+
"chai": "~1.9.0",
|
|
12
|
+
"jshint": "^2.5.10",
|
|
13
|
+
"jshint-stylish": "^1.0.0",
|
|
12
14
|
"mocha": "~1.17.1",
|
|
13
|
-
"
|
|
15
|
+
"nodemon": "^1.2.1"
|
|
14
16
|
},
|
|
15
17
|
"scripts": {
|
|
16
|
-
"test": "mocha tests/*"
|
|
18
|
+
"test": "jshint --reporter node_modules/jshint-stylish/stylish.js index.js && mocha tests/*",
|
|
19
|
+
"watch": "nodemon -q -w index.js -w tests/ -x npm test"
|
|
17
20
|
},
|
|
18
21
|
"repository": {
|
|
19
22
|
"type": "git",
|