Skip to content

Commit

Permalink
Version 0.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Bahman Fakhr Sabahi committed Apr 1, 2015
1 parent 3cf73d3 commit c0e36ad
Show file tree
Hide file tree
Showing 9 changed files with 607 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
node_modules/
5 changes: 5 additions & 0 deletions .npmignore
@@ -0,0 +1,5 @@
.git/
node_modules/
test/
.gitignore
.npmignore
21 changes: 21 additions & 0 deletions LICENSE
@@ -0,0 +1,21 @@
Copyright (c) 2013-2014 inveris OHG
Author Peter Rottmann <rottmann@inveris.de>
Licensed under the MIT license.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
42 changes: 41 additions & 1 deletion README.md
@@ -1,2 +1,42 @@
# apidoc-swagger
apidoc and swagger are two nice projects which are focusing on documentation of APIs. This project is a middle tier which tries to bring them together in a sense that it uses apidoc to convert inline documentation comments into json schema and later convert it to swagger json schmea.
apidoc and swagger are two nice projects which are focusing on documentation of APIs.
This project is a middle tier which tries to bring them together in a sense that:
> It uses apidoc to convert inline documentation comments into json schema and later convert it to swagger json schmea.
Uses the [apidoc-core](https://github.com/apidoc/apidoc-core) library.

## How It Works

By putting in line comments in the source code like this in javascript, you will get `swagger.json` file which can be served to [swagger-ui](https://github.com/swagger-api/swagger-ui) to generate html overview of documentation.

`/api/foo.js`:
```js
/**
* @api {get} /user/id Request User information
* @apiName GetUser
* @apiGroup User
*
* @apiParam {Number} id Users unique ID.
*
* @apiSuccess {String} firstname Firstname of the User.
* @apiSuccess {String} lastname Lastname of the User.
*/
```


## Installation

`npm install apidoc-swagger -g`


Current version unlocks most of the basic capabilities of both projects and improvement is in progress.

## Example

`apidoc-swagger -i example/ -o doc/`



Have a look at [apidoc](https://github.com/apidoc/apidoc) for full functionality overview and capabilities of apidoc.

To read more about how swagger works refer to [swagger-ui](https://github.com/swagger-api/swagger-ui) and [swagger-spec](https://github.com/swagger-api/swagger-spec) for details of `swagger.json`.
145 changes: 145 additions & 0 deletions bin/apidocSwagger.js
@@ -0,0 +1,145 @@
#!/usr/bin/env node

'use strict';

/*
* apidoc-swagger
*
* Copyright (c) 2015 Exact
* Author Bahman Fakhr Sabahi <bahman.sabahi@exact.com>
* Licensed under the MIT license.
*/

var path = require('path');
var nomnom = require('nomnom');
var apidocSwagger = require('../lib/index');

var argv = nomnom
.option('file-filters', { abbr: 'f', 'default': '.*\\.(clj|coffee|cs|dart|erl|go|java|js|php?|py|rb|ts|pm)$',
help: 'RegEx-Filter to select files that should be parsed (multiple -f can be used).' })

.option('exclude-filters', { abbr: 'e', 'default': '',
help: 'RegEx-Filter to select files / dirs that should not be parsed (many -e can be used).', })

.option('input', { abbr: 'i', 'default': './', help: 'Input / source dirname.' })

.option('output', { abbr: 'o', 'default': './doc/', help: 'Output dirname.' })

.option('verbose', { abbr: 'v', flag: true, 'default': false, help: 'Verbose debug output.' })

.option('help', { abbr: 'h', flag: true, help: 'Show this help information.' })

.option('debug', { flag: true, 'default': false, help: 'Show debug messages.' })

.option('color', { flag: true, 'default': true, help: 'Turn off log color.' })

.option('parse', { flag: true, 'default': false,
help: 'Parse only the files and return the data, no file creation.' })

.option('parse-filters' , { help: 'Optional user defined filters. Format name=filename' })
.option('parse-languages', { help: 'Optional user defined languages. Format name=filename' })
.option('parse-parsers' , { help: 'Optional user defined parsers. Format name=filename' })
.option('parse-workers' , { help: 'Optional user defined workers. Format name=filename' })

.option('silent', { flag: true, 'default': false, help: 'Turn all output off.' })

.option('simulate', { flag: true, 'default': false, help: 'Execute but not write any file.' })

// markdown settings
.option('markdown', { flag: true, 'default': true, help: 'Turn off markdown parser.' })

.option('marked-config', { 'default': '',
help: 'Enable custom markdown parser configs. It will overwite all other marked settings.' })

.option('marked-gfm', { flag: true, 'default': true,
help: 'Enable GitHub flavored markdown.' })

.option('marked-tables', { flag: true, 'default': true,
help: 'Enable GFM tables. This option requires the gfm option to be true.' })

.option('marked-breaks', { flag: true, 'default': false,
help: 'Enable GFM line breaks. This option requires the gfm option to be true.' })

.option('marked-pedantic', { flag: true, 'default': false,
help: 'Conform to obscure parts of markdown.pl as much as possible.' })

.option('marked-sanitize', { flag: true, 'default': false,
help: 'Sanitize the output. Ignore any HTML that has been input.' })

.option('marked-smartLists', { flag: true, 'default': false,
help: 'Use smarter list behavior than the original markdown.' })

.option('marked-smartypants', { flag: true, 'default': false,
help: 'Use \'smart\' typograhic punctuation for things like quotes and dashes.' })

.parse()
;

/**
* Transform parameters to object
*
* @param {String|String[]} filters
* @returns {Object}
*/
function transformToObject(filters) {
if ( ! filters)
return;

if (typeof(filters) === 'string')
filters = [ filters ];

var result = {};
filters.forEach(function(filter) {
var splits = filter.split('=');
if (splits.length === 2) {
var obj = {};
result[splits[0]] = path.resolve(splits[1], '');
}
});
return result;
}

/**
* Sets configuration for markdown
*
* @param {Array} argv
* @returns {Object}
*/
function resolveMarkdownOptions(argv) {
if (argv['marked-config']) {
return require(path.resolve(argv['marked-config']));
} else {
return {
gfm : argv['marked-gfm'],
tables : argv['marked-tables'],
breaks : argv['marked-breaks'],
pedantic : argv['marked-pedantic'],
sanitize : argv['marked-sanitize'],
smartLists : argv['marked-smartLists'],
smartypants: argv['marked-smartypants']
};
}
}

var options = {
excludeFilters: argv['exclude-filters'],
includeFilters: argv['file-filters'],
src : argv['input'],
dest : argv['output'],
verbose : argv['verbose'],
debug : argv['debug'],
parse : argv['parse'],
colorize : argv['color'],
filters : transformToObject(argv['parse-filters']),
languages : transformToObject(argv['parse-languages']),
parsers : transformToObject(argv['parse-parsers']),
workers : transformToObject(argv['parse-workers']),
silent : argv['silent'],
simulate : argv['simulate'],
markdown : argv['markdown'],
marked : resolveMarkdownOptions(argv)
};

if (apidocSwagger.createApidocSwagger(options) === false) {
process.exit(1);
}
85 changes: 85 additions & 0 deletions lib/apidocToSwagger.js
@@ -0,0 +1,85 @@
var _ = require('lodash');

var swagger = {
swagger : "2.0",
info : {},
paths : {}
};

function toSwagger(apidocJson, projectJson) {
swagger.info = addInfo(projectJson);
swagger.paths = extractPaths(apidocJson);
return swagger;
}


function addInfo(projectJson) {
var info = {};
info["title"] = projectJson.title;
info["version"] = projectJson.version;
info["description"] = projectJson.description;
return info;
}

function extractPaths(apidocJson){
var apiPaths = groupByUrl(apidocJson);
var paths = {};
for (var i = 0; i < apiPaths.length; i++) {
paths[apiPaths[i].url] = extractVerbs(apiPaths[i].verbs);
}
return paths;
}

function extractVerbs(verbs){
var pathItemObject = {};
for (var i = 0; i < verbs.length; i++) {
//TODO: if there are multiple version of documentation for same api/verb pick latest!
pathItemObject[verbs[i].type] = createOperationObject(verbs[i]);
}
return pathItemObject;
}

function groupByUrl(apidocJson) {
return _.chain(apidocJson)
.groupBy("url")
.pairs()
.map(function (element) {
return _.object(_.zip(["url", "verbs"], element));
})
.value();
}

function createOperationObject(verb) {
var operationObject = {
description : verb.title,
summary : verb.description,
tags : [verb.group],
parameters : verb.parameter ? createParameters(verb.parameter): {}
};
return operationObject;
}

function createParameters(apiParameters) {
var parameterArray = [];
var parameters = [];
for (field in apiParameters.fields) {
if (Array.isArray(apiParameters.fields[field])) {
parameterArray = apiParameters.fields[field];
}
}
for (var i = 0; i < parameterArray.length; i++) {
var parameter = {
name : parameterArray[i].field,
in : "query",
description : parameterArray[i].description,
required : !parameterArray[i].optional,
type : parameterArray[i].type,
};
parameters.push(parameter);
}
return parameters;
}

module.exports = {
toSwagger: toSwagger
};

0 comments on commit c0e36ad

Please sign in to comment.