Skip to content

Commit

Permalink
Moved from Whiteboard to Documentarian
Browse files Browse the repository at this point in the history
  • Loading branch information
mpociot committed May 11, 2016
1 parent 6e7c50f commit 02d34fd
Show file tree
Hide file tree
Showing 6 changed files with 388 additions and 76 deletions.
39 changes: 18 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
## Laravel API Documentation Generator (WIP)
# Documentarian
#### Simply write beautiful API documentation.
========

`php artisan api:gen --routePrefix=settings/api/*`
This project is a PHP port of the popular [Slate](https://github.com/tripit/slate) API documentation tool.

> If PHP is not your thing and you're more into nodeJS, why not give [Whiteboard](https://github.com/mpociot/whiteboard) a try?
### Install
<a href="http://www.marcelpociot.com/whiteboard/"><img src="http://www.marcelpociot.com/git/whiteboard_responsive.jpg" style="width: 100%" alt="Documentarian" /></a>

Require this package with composer using the following command:
Check out a Documentarian [example API documentation](http://www.marcelpociot.com/whiteboard/).

```bash
composer require mpociot/laravel-apidoc-generator
```
Go to your `config/app.php` and add the service provider:
The documentation is available at [http://marcelpociot.com/documentarian/installation](http://marcelpociot.com/documentarian/installation)

```php
Mpociot\ApiDoc\ApiDocGeneratorServiceProvider::class
```

### Usage
### Slate / Whiteboard compatibility
Since both Documentarian and Slate use regular markdown files to render the API documentation, your existing Slate API documentation should work just fine. If you encounter any issues, please [submit an issue](https://github.com/mpociot/documentarian/issues).

### In depth documentation
For further documentation, read the [Slate Wiki](https://github.com/tripit/slate/wiki).

```
php artisan api:generate
{--output=public/docs : The output path for the generated documentation}
{--routePrefix= : The route prefix to use for generation - * can be used as a wildcard}
{--routes=* : The route names to use for generation - if no routePrefix is provided}
{--actAsUserId= : The user ID to use for API response calls}
```
### Documentations built with Documentarian

Feel free to submit a PR with a link to your documentation.

### License
### Contributors

The Laravel API Documentation Generator is free software licensed under the MIT license.
Slate was built by [Robert Lord](https://lord.io) while at [TripIt](http://tripit.com).

Documentarian was built by Marcel Pociot.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "mpociot/laravel-apidoc-generator",
"name": "mpociot/laravel-apidoc-generators",
"license": "MIT",
"description": "Generate beautiful API documentation from your Laravel / Lumen application",
"keywords": ["API","Documentation","Laravel"],
Expand All @@ -13,7 +13,8 @@
"require": {
"php": ">=7.0.0",
"laravel/framework": "~5.0",
"phpdocumentor/reflection-docblock": "~2.0"
"phpdocumentor/reflection-docblock": "~2.0",
"mpociot/documentarian": "dev-master"
},
"require-dev": {
"phpunit/phpunit": "~5.0",
Expand Down
95 changes: 89 additions & 6 deletions src/Mpociot/ApiDoc/ApiDocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ private function getRouteRules($route)
return [];
}

/**
* @param $arr
* @param $first
* @param $last
* @return string
*/
protected function fancy_implode($arr, $first, $last)
{
array_push($arr, implode($last, array_splice($arr, -2)));
return implode($first, $arr);
}

/**
* @param $rule
* @param $attributeData
Expand All @@ -121,43 +133,114 @@ protected function parseRule($rule, &$attributeData)
case 'required':
$attributeData['required'] = true;
break;
case 'accepted':
$attributeData['type'] = 'boolean';
break;
case 'after':
$attributeData['type'] = 'date';
$attributeData['description'][] = 'Must be a date after: `' . date(DATE_RFC850, strtotime($parameters[0])) . '`';
break;
case 'alpha':
$attributeData['description'][] = 'Only alphabetic characters allowed';
break;
case 'alpha_dash':
$attributeData['description'][] = 'Allowed: alpha-numeric characters, as well as dashes and underscores.';
break;
case 'alpha_num':
$attributeData['description'][] = 'Only alpha-numeric characters allowed';
break;
case 'in':
$attributeData['description'][] = implode(' or ', $parameters);
$attributeData['description'][] = $this->fancy_implode($parameters, ', ', ' or ');
break;
case 'not_in':
$attributeData['description'][] = 'Not in: ' . implode(' or ', $parameters);
$attributeData['description'][] = 'Not in: ' . $this->fancy_implode($parameters, ', ', ' or ');
break;
case 'min':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Minimum: `' . $parameters[0] . '`';
break;
case 'max':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Maximum: `' . $parameters[0] . '`';
break;
case 'between':
$attributeData['description'][] = 'Between: `' . $parameters[0] . '` and ' . $parameters[1];
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Between: `' . $parameters[0] . '` and `' . $parameters[1] . '`';
break;
case 'before':
$attributeData['type'] = 'date';
$attributeData['description'][] = 'Must be a date preceding: `' . date(DATE_RFC850, strtotime($parameters[0])) . '`';
break;
case 'date_format':
$attributeData['description'][] = 'Date format: ' . $parameters[0];
$attributeData['type'] = 'date';
$attributeData['description'][] = 'Date format: `' . $parameters[0] . '`';
break;
case 'different':
$attributeData['description'][] = 'Must have a different value than parameter: `' . $parameters[0] . '`';
break;
case 'digits':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Must have an exact length of `' . $parameters[0] . '`';
break;
case 'digits_between':
$attributeData['type'] = 'numeric';
$attributeData['description'][] = 'Must have a length between `' . $parameters[0] . '` and `' . $parameters[1] . '`';
break;
case 'image':
$attributeData['description'][] = 'Must be an image (jpeg, png, bmp, gif, or svg)';
break;
case 'json':
$attributeData['type'] = 'string';
$attributeData['description'][] = 'Must be a valid JSON string.';
break;
case 'mimetypes':
case 'mimes':
$attributeData['description'][] = 'Allowed mime types: ' . implode(', ', $parameters);
$attributeData['description'][] = 'Allowed mime types: ' . $this->fancy_implode($parameters, ', ', ' or ');
break;
case 'required_if':
$attributeData['description'][] = 'Required if `' . $parameters[0] . '` is `' . $parameters[1] . '`';
break;
case 'required_unless':
$attributeData['description'][] = 'Required unless `' . $parameters[0] . '` is `' . $parameters[1] . '`';
break;
case 'required_with':
$attributeData['description'][] = 'Required if the parameters ' . $this->fancy_implode($parameters, ', ', ' or ') . ' are present.';
break;
case 'required_with_all':
$attributeData['description'][] = 'Required if the parameters ' . $this->fancy_implode($parameters, ', ', ' and ') . ' are present.';
break;
case 'required_without':
$attributeData['description'][] = 'Required if the parameters ' . $this->fancy_implode($parameters, ', ', ' or ') . ' are not present.';
break;
case 'required_without_all':
$attributeData['description'][] = 'Required if the parameters ' . $this->fancy_implode($parameters, ', ', ' and ') . ' are not present.';
break;
case 'same':
$attributeData['description'][] = 'Must be the same as `' . $parameters[0] . '`';
break;
case 'size':
$attributeData['description'][] = 'Must have the size of `' . $parameters[0] . '`';
break;
case 'timezone':
$attributeData['description'][] = 'Must be a valid timezone identifier';
break;
case 'exists':
$attributeData['description'][] = 'Valid ' . Str::singular($parameters[0]) . ' ' . $parameters[1];
break;
case 'active_url':
$attributeData['type'] = 'url';
break;
case 'regex':
$attributeData['type'] = 'string';
$attributeData['description'][] = 'Must match this regular expression: `' . $parameters[0] . '`';
break;
case 'boolean':
case 'array':
case 'date':
case 'email':
case 'image':
case 'string':
case 'integer':
case 'json':
case 'numeric':
case 'url':
case 'ip':
Expand Down
46 changes: 6 additions & 40 deletions src/Mpociot/ApiDoc/Commands/GenerateDocumentation.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Route;
use Mpociot\ApiDoc\ApiDocGenerator;
use Mpociot\Documentarian\Documentarian;
use phpDocumentor\Reflection\DocBlock;
use Symfony\Component\Process\Process;

Expand Down Expand Up @@ -94,20 +95,12 @@ private function writeMarkdown($parsedRoutes)
{
$outputPath = $this->option('output');

$markdown = view('apidoc::whiteboard')->with('parsedRoutes', $parsedRoutes);
$documentarian = new Documentarian();

$markdown = view('apidoc::documentarian')->with('parsedRoutes', $parsedRoutes);

if (!is_dir($outputPath)) {
$this->cloneWhiteboardRepository();

if ($this->confirm('Would you like to install the NPM dependencies?', true)) {
$process = (new Process('npm set progress=false && npm install', $outputPath))->setTimeout(null);
if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) {
$process->setTty(true);
}
$process->run(function ($type, $line) {
$this->info($line);
});
}
$documentarian->create($outputPath);
}

file_put_contents($outputPath . DIRECTORY_SEPARATOR . 'source' . DIRECTORY_SEPARATOR . 'index.md', $markdown);
Expand All @@ -116,36 +109,9 @@ private function writeMarkdown($parsedRoutes)

$this->info('Generating API HTML code');

$process = (new Process('npm run-script generate', $outputPath))->setTimeout(null);
if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) {
$process->setTty(true);
}
$process->run(function ($type, $line) {
$this->info($line);
});
$documentarian->generate($outputPath);

$this->info('Wrote HTML documentation to: ' . $outputPath . '/public/index.html');
}

/**
* Clone the Whiteboard nodejs repository
*/
private function cloneWhiteboardRepository()
{
$outputPath = $this->option('output');

mkdir($outputPath, 0777, true);

// Clone whiteboard
$this->info('Cloning whiteboard repository.');

$process = (new Process('git clone ' . self::WHITEBOARD_REPOSITORY . ' ' . $outputPath))->setTimeout(null);
if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) {
$process->setTty(true);
}
$process->run(function ($type, $line) {
$this->info($line);
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
search: true

toc_footers:
- <a href='http://github.com/mpociot/whiteboard'>Documentation Powered by Whiteboard</a>
- <a href='http://github.com/mpociot/documentarian'>Documentation Powered by Whiteboard</a>
---

# Info
Expand All @@ -36,6 +36,7 @@
-d "{{$attribute}}"="dummy" \
@endforeach
@endif

```

```javascript
Expand Down Expand Up @@ -68,6 +69,7 @@
### HTTP Request
@foreach($parsedRoute['methods'] as $method)
`{{$method}} {{$parsedRoute['uri']}}`

@endforeach
@if(count($parsedRoute['parameters']))

Expand Down
Loading

0 comments on commit 02d34fd

Please sign in to comment.