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 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.1",
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
- .trim();
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.trim();
191
+ line.source = trim(line.source);
190
192
 
191
- if (line.source.match(/^@(\w+)/)) {
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').trim();
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
- // console.log('line (2)', line);
312
- // console.log(' clean:', line.replace(RE_COMMENT_LINE, ''));
313
- chunk.push({source: line.replace(RE_COMMENT_LINE, ''), number: number - 1});
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;
@@ -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 optionalrest names `@tag [...name] desc`', function() {
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
  });