nodoc
Version:
A simple and 'low-level' source code comments parser and gitHub flavored markdown API documentation generator.
305 lines (210 loc) • 8.41 kB
Markdown
# nodoc
A simple and 'low-level' source code comments parser and documentation generator.
> Oops, this doc is generated by nodoc itself !
[](http://badge.fury.io/js/nodoc)
[](https://david-dm.org/dracupid/nodoc)
## Supported Languages
- CoffeeScript
> Other languagage, especially javascript, will be supported soon.
#### Language Name Aliases
Use lower case, used both for language option and extname recognization.
```javascript
{
"coffee": "coffee",
"coffeescript": "coffee",
"js": "javascript",
"javascript": "javascript"
}
```
## Usage
0. Convert comment block to an object as following:
#### Parsed Comment Object
```javascript
{
name: 'parseFile',
description: 'Parse source code from file. Use Promise instead of callback',
tags: [ [Object], [Object], [Object], [Object] ], // tag objects array
lineNum: 78
}
```
#### Tag Object
```javascript
{
tagName: 'param',
type: 'string', // only @param, @property, @option, @return
name: 'srcPath', // only @param, @property, @option
description: 'Path of source code file'
}
```
Tags are only key-value pairs, except `@param`, `@return`, `@property`, `@option`. They may have extra type and (maybe) name.
```javascript
var doc = require('nodoc');
// From file
doc.parser.parseFile('./src/parser/index.coffee').then(function(res){});
res = doc.parser.parseFileSync('./src/parser/index.coffee')
//From source code
doc.parser.parse('A piece of source code', 'coffee').then(function(res){});
```
0. Generate gitHub flavored markdown API doc from comments.
```javascript
var doc = require('nodoc'),
fs = require('fs');
doc.generate('./src/parser/index.coffee', {
moduleName: 'parser',
moduleDesc: 'This is a parser!'
}).then(function(markdown){
fs.writeFileSync('./api.md', markdown);
});
```
In this case, predefined tags will make effects.
### Predefined tags
+ `@private`: Hidden in the generated document.
+ `@nodoc`: Same behavior as `@private`, but they are differ in semantics.
+ `@alias`: Shown as an addition of function name.
+ `@prefix`: Add a custom prefix to function name.
+ `@noPrefix`: Only preserve the real name, regard `util.promisify` as `promisify`.
## Comment format
Of course, you need to write your comments in a standard way to make a parser work.
Such as:
```coffeescript
###*
* Generate formatted markdown API document from source code
* @param {string} srcPath Path of source code file
* @param {Object={}} opts Options, optional
* @return {Promise} Resolve formatted markdown
* @example
* ` ``javascript
* nodoc.generate('./src/index.coffee').then(function(md){
* console.log(md);
* });
* ` ``
###
```
As you can see, you can use **markdown** in your comment!
> Reference: [jsdoc](http://usejsdoc.org/)
## API
- #### <a href="./src/index.coffee?source#L91" target="_blank"><b>generate (srcPath, opts) <small>(alias: render)</small> </b></a>
Generate formatted markdown API document from source code
- **param**: `srcPath` { _string_ }
Path of the source code file
- **param**: `opts` { _Object=_ }
Options
```javascript
{
moduleName: '', // module name of the file, or it will be auto set to file name, of parent directory name for `index` file.
moduleDesc: '', // module decription
template: '', // custom template
tplData: {}, // addition template data
cwd: process.cwd() // current working directory
language: '' // specify the language, or it will be auto recognized by extname
rule: {} // specific parser rule, items vary from parsers
}
```
- **return**: { _Promise_ }
Resolve markdown
- **example**:
```javascript
nodoc.generate('./src/index.coffee').then(function(md){
console.log(md);
});
```
- #### <a href="./src/index.coffee?source#L121" target="_blank"><b>parser </b></a>
Parser module, see below for details.
## Parser Module
- #### <a href="./src/parser/index.coffee?source#L24" target="_blank"><b>parser.setParser (name, parser)</b></a>
Create a new parser or override an old ones
- **param**: `name` { _string|Array_ }
parser's name/language (and aliases)
- **param**: `parser` { _Object_ }
parser object, see below
- #### <a href="./src/parser/index.coffee?source#L47" target="_blank"><b>parser.parse (source, language, opts)</b></a>
Parse source code directly.
- **param**: `source` { _string_ }
source code
- **param**: `language` { _string_ }
specify source language
- **param**: `opts` { _Object=_ }
option, optional
- **return**: { _Array_ }
parsed comments object **array**
- **example**:
```javascript
nodoc.parser.parse("This is source code with comments", "coffee").then(function(comments){
console.log(comments);
})
```
- #### <a href="./src/parser/index.coffee?source#L86" target="_blank"><b>parser.parseFile (filePath, opts = {})</b></a>
Parse source code from file. Use Promise instead of callback
- **param**: `filePath` { _string_ }
souce file path
- **param**: `opts` { _Object={}_ }
options
- **return**: { _Promise_ }
resolve parsed comment object **array**
- **example**:
```javascript
nodoc.parser.parseFile("index.coffee", {cwd: './src'}).then(function(comments){
console.log(comments);
});
```
- #### <a href="./src/parser/index.coffee?source#L94" target="_blank"><b>parser.parseFileSync ()</b></a>
Synchronous version of parseFile
- **return**: { _Array_ }
parsed comment object **array**
- #### <a href="./src/parser/index.coffee?source#L109" target="_blank"><b>parser.setRule (language, rule)</b></a>
Set parser's rule
- **param**: `language` { _string_ }
parser's name/language
- **param**: `rule` { _Object_ }
parser's rule object
- **example**:
```javascript
nodoc.parser.setRule('coffee', {
commentReg: /#?([\s\S]+?)#\s+([\w\.]+)/g
});
```
## Write your own template
Nodoc uses [underscore template](http://underscorejs.org/#template) to render the markdown template. You need to realize that template is not HTML's privilege.
If you don't want to use the default template, you can use your own.
```javascript
doc.generate('./src/parser/index.coffee', {
template: 'Here is your own template'
tplData: {} // You can use this object to add custom data to your template
}).then(function(markdown){});
```
However, if you even want to use a alternative template engine, please use parser module directly.
## Write your own language parser
If the languages you use is not supported by nodoc, you can write your own parser and register it by `parser.setParser`. If you want your parser to be a part of nodoc, please make a pull request, it is warmly welcomed.
A parser should provide follow APIs:
### Parser API
- #### <a href="./src/parser/coffee.coffee?source#L52" target="_blank"><b>parse (source, localRule)</b></a>
Parse comment from source code
- **param**: `source` { _string_ }
source code
- **param**: `localRule` { _Object=_ }
optional, custom rule object, use once
- **return**: { _Array_ }
parsed comments object array
- #### <a href="./src/parser/coffee.coffee?source#L72" target="_blank"><b>setRule (ruleObj)</b></a>
Set the rule of the parser
- **param**: `ruleObj` { _Object_ }
rule object
- #### <a href="./src/parser/coffee.coffee?source#L78" target="_blank"><b>getRule ()</b></a>
Hmm..., I'd like to use this to generate document.
- **return**: { _Object_ }
rule object
### Rule
A parser uses and is supposed to expose the rules it uses to parse the code.
#### Rules for coffee parser
```javascript
{ commentReg: /###\*([\s\S]+?)###\s+([\w\.@'"]+)/g,
splitReg: /^\s+\* ?@/m,
tagNameReg: /^([\w\.]+)\s*/,
typeReg: /^\{(.+|}?)\}\s*/,
nameReg: /^([\w\.]+)\s*/,
nameTags: [ 'param', 'property', 'option' ],
descriptionReg: /^([\s\S]*)/,
removePrefix: /self\.|this\.|@|'|"/g }
```
### License
MIT