Comparing version 0.5.3 to 0.6.0
@@ -0,1 +1,10 @@ | ||
0.6.0 / 2014-11-27 | ||
================== | ||
* Add complex jsdoc annotations | ||
* Add support for more tags | ||
* Add typesDescription field | ||
* Fix "skipPrefixes incorrectly assumes option.raw=false" | ||
* Fix "White spaces in the tag type string break the parsing of tags" | ||
0.5.3 / 2014-10-06 | ||
@@ -2,0 +11,0 @@ ================== |
102
lib/dox.js
@@ -66,3 +66,3 @@ /*! | ||
, linterPrefixes = options.skipPrefixes || ['jslint', 'jshint', 'eshint'] | ||
, skipPattern = new RegExp('^<p>('+ linterPrefixes.join('|') + ')') | ||
, skipPattern = new RegExp('^' + (options.raw ? '' : '<p>') + '('+ linterPrefixes.join('|') + ')') | ||
, lineNum = 1 | ||
@@ -101,7 +101,7 @@ , lineNumStarting = 1 | ||
ignore = '!' == js[i]; | ||
// if the current character isn't whitespace and isn't an ignored comment, | ||
// back up one character so we don't clip the contents | ||
if (' ' !== js[i] && '\n' !== js[i] && '\t' !== js[i] && '!' !== js[i]) i--; | ||
// end comment | ||
@@ -246,3 +246,40 @@ } else if (withinMultiline && !withinSingle && '*' == js[i] && '/' == js[i+1]) { | ||
//TODO: Find a smarter way to do this | ||
/** | ||
* Extracts different parts of a tag by splitting string into pieces separated by whitespace. If the white spaces are | ||
* somewhere between curly braces (which is used to indicate param/return type in JSDoc) they will not be used to split | ||
* the string. This allows to specify jsdoc tags without the need to eliminate all white spaces i.e. {number | string} | ||
* | ||
* @param str The tag line as a string that needs to be split into parts | ||
* @returns {Array.<string>} An array of strings containing the parts | ||
*/ | ||
exports.extractTagParts = function(str) { | ||
var level = 0, | ||
extract = '', | ||
split = []; | ||
str.split('').forEach(function(c) { | ||
if(c.match(/\s/) && level === 0) { | ||
split.push(extract); | ||
extract = ''; | ||
} else { | ||
if(c === '{') { | ||
level++; | ||
} else if (c === '}') { | ||
level--; | ||
} | ||
extract += c; | ||
} | ||
}); | ||
split.push(extract); | ||
return split.filter(function(str) { | ||
return str.length > 0; | ||
}); | ||
}; | ||
/** | ||
* Parse tag string "@param {Array} name description" etc. | ||
@@ -258,3 +295,3 @@ * | ||
, lines = str.split('\n') | ||
, parts = lines[0].split(/ +/) | ||
, parts = exports.extractTagParts(lines[0]) | ||
, type = tag.type = parts.shift().replace('@', ''); | ||
@@ -270,6 +307,6 @@ | ||
case 'param': | ||
tag.types = exports.parseTagTypes(parts.shift()); | ||
var typeString = parts.shift(); | ||
tag.name = parts.shift() || ''; | ||
tag.description = parts.join(' '); | ||
tag.optional = exports.parseParamOptional(tag); | ||
exports.parseTagTypes(typeString, tag); | ||
break; | ||
@@ -279,3 +316,3 @@ case 'define': | ||
case 'returns': | ||
tag.types = exports.parseTagTypes(parts.shift()); | ||
exports.parseTagTypes(parts.shift(), tag); | ||
tag.description = parts.join(' '); | ||
@@ -304,3 +341,3 @@ break; | ||
case 'type': | ||
tag.types = exports.parseTagTypes(parts.shift()); | ||
exports.parseTagTypes(parts.shift(), tag); | ||
break; | ||
@@ -334,3 +371,16 @@ case 'lends': | ||
* Parse tag type string "{Array|Object}" etc. | ||
* This function also supports complex type descriptors like in jsDoc or even the enhanced syntax used by the | ||
* [google closure compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler#types) | ||
* | ||
* The resulting array from the type descriptor `{number|string|{name:string,age:number|date}}` would look like this: | ||
* | ||
* [ | ||
* 'number', | ||
* 'string', | ||
* { | ||
* age: ['number', 'date'], | ||
* name: ['string'] | ||
* } | ||
* ] | ||
* | ||
* @param {String} str | ||
@@ -341,6 +391,32 @@ * @return {Array} | ||
exports.parseTagTypes = function(str) { | ||
return str | ||
.replace(/[{}]/g, '') | ||
.split(/ *[|,\/] */); | ||
exports.parseTagTypes = function(str, tag) { | ||
var Parser = require('jsdoctypeparser').Parser; | ||
var Builder = require('jsdoctypeparser').Builder; | ||
var result = new Parser().parse(str.substr(1, str.length - 2)); | ||
var types = (function transform(type) { | ||
if(type instanceof Builder.TypeUnion) { | ||
return type.types.map(transform); | ||
} else if(type instanceof Builder.TypeName) { | ||
return type.name; | ||
} else if(type instanceof Builder.RecordType) { | ||
return type.entries.reduce(function(obj, entry) { | ||
obj[entry.name] = transform(entry.typeUnion); | ||
return obj; | ||
}, {}); | ||
} else { | ||
return type.toString(); | ||
} | ||
}(result)); | ||
if(tag) { | ||
tag.types = types; | ||
tag.typesDescription = result.toHtml(); | ||
tag.optional = (tag.name && tag.name.slice(0,1) === '[') || result.optional; | ||
tag.nullable = result.nullable; | ||
tag.nonNullable = result.nonNullable; | ||
tag.variable = result.variable; | ||
} | ||
return types; | ||
}; | ||
@@ -350,3 +426,3 @@ | ||
* Determine if a parameter is optional. | ||
* | ||
* | ||
* Examples: | ||
@@ -353,0 +429,0 @@ * JSDoc: {Type} [name] |
{ | ||
"name": "dox", | ||
"description": "Markdown / JSdoc documentation generator", | ||
"version": "0.5.3", | ||
"version": "0.6.0", | ||
"author": "TJ Holowaychuk <tj@vision-media.ca>", | ||
@@ -13,2 +13,3 @@ "contributors": [ | ||
"Nathan Rajlich <nathan@tootallnate.net>", | ||
"Gion Kunz <gion.kunz@gmail.com>", | ||
"ForbesLindesay" | ||
@@ -30,4 +31,5 @@ ], | ||
"dependencies": { | ||
"marked": ">=0.3.1", | ||
"commander": "0.6.1" | ||
"commander": "0.6.1", | ||
"jsdoctypeparser": "^1.1.1", | ||
"marked": ">=0.3.1" | ||
}, | ||
@@ -34,0 +36,0 @@ "devDependencies": { |
# Dox | ||
[![Build Status](https://travis-ci.org/visionmedia/dox.svg?branch=master)](https://travis-ci.org/visionmedia/dox) | ||
[![Build Status](https://travis-ci.org/tj/dox.svg?branch=master)](https://travis-ci.org/tj/dox) | ||
@@ -218,3 +218,3 @@ Dox is a JavaScript documentation generator written with [node](http://nodejs.org). Dox no longer generates an opinionated structure or style for your docs, it simply gives you a JSON representation, allowing you to use _markdown_ and _JSDoc_-style tags. | ||
* @param {String} str | ||
* @param {Object} options | ||
* @param {{stream: Writable}} options | ||
* @return {Object} exports for chaining | ||
@@ -239,3 +239,3 @@ */ | ||
{ type: 'param', | ||
types: [ 'Object' ], | ||
types: [ { stream: ['Writable'] } ], | ||
name: 'options', | ||
@@ -250,2 +250,92 @@ description: '' }, | ||
#### Complex jsdoc tags | ||
dox supports all jsdoc type strings specified in the [jsdoc documentation](http://usejsdoc.org/tags-type.html). You can | ||
specify complex object types including optional flag `=`, nullable `?`, non-nullable `!` and variable arguments `...`. | ||
Additionally you can use `typesDescription` which contains formatted HTML for displaying complex types. | ||
```js | ||
/** | ||
* Generates a person information string based on input. | ||
* | ||
* @param {string | {name: string, age: number | date}} name Name or person object | ||
* @param {{separator: string} =} options An options object | ||
* @return {string} The constructed information string | ||
*/ | ||
exports.generatePersonInfo = function(name, options) { | ||
var str = ''; | ||
var separator = options && options.separator ? options.separator : ' '; | ||
if(typeof name === 'object') { | ||
str = [name.name, '(', name.age, ')'].join(separator); | ||
} else { | ||
str = name; | ||
} | ||
}; | ||
``` | ||
yields: | ||
```js | ||
tags: | ||
[ | ||
{ | ||
"tags": [ | ||
{ | ||
"type": "param", | ||
"name": "name", | ||
"description": "Name or person object", | ||
"types": [ | ||
"string", | ||
{ | ||
"name": [ | ||
"string" | ||
], | ||
"age": [ | ||
"number", | ||
"date" | ||
] | ||
} | ||
], | ||
"typesDescription": "<code>string</code>|{ name: <code>string</code>, age: <code>number</code>|<code>date</code> }", | ||
"optional": false, | ||
"nullable": false, | ||
"nonNullable": false, | ||
"variable": false | ||
}, | ||
{ | ||
"type": "param", | ||
"name": "options", | ||
"description": "An options object", | ||
"types": [ | ||
{ | ||
"separator": [ | ||
"string" | ||
] | ||
} | ||
], | ||
"typesDescription": "{ separator: <code>string</code> }|<code>undefined</code>", | ||
"optional": true, | ||
"nullable": false, | ||
"nonNullable": false, | ||
"variable": false | ||
}, | ||
{ | ||
"type": "return", | ||
"types": [ | ||
"string" | ||
], | ||
"typesDescription": "<code>string</code>", | ||
"optional": false, | ||
"nullable": false, | ||
"nonNullable": false, | ||
"variable": false, | ||
"description": "The constructed information string" | ||
} | ||
] | ||
``` | ||
### Code | ||
@@ -252,0 +342,0 @@ |
36051
592
449
3
+ Addedjsdoctypeparser@^1.1.1
+ Addedjsdoctypeparser@1.2.0(transitive)
+ Addedlodash@3.10.1(transitive)