├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── composer.json ├── i_stand.png └── src ├── Attributes └── SwaggerSection.php ├── Commands └── GenerateDocsCommand.php ├── Controllers ├── DocumentationController.php └── IssueController.php ├── Helpers.php ├── Middleware ├── BasicAuthentication.php └── SetJsonResponseMiddleware.php ├── Responses ├── BaseResponse.php ├── DeleteResponse.php ├── GetResponse.php ├── PatchResponse.php ├── PostResponse.php └── PutResponse.php ├── Routes └── web.php ├── Sections ├── Paths.php ├── Schemas.php └── Tags.php ├── Swagger.php ├── SwaggerServiceProvider.php ├── config └── swagger.php ├── custom-assets ├── css │ ├── bootstrap.min.css │ └── swagger-ui.css ├── images │ ├── swagger.png │ └── theme.png ├── js │ ├── bootstrap.min.js │ ├── jquery-3.6.0.min.js │ ├── js-yaml.min.js │ ├── popper.min.js │ ├── swagger-ui-bundle.js │ └── swagger-ui-standalone-preset.js └── themes │ ├── theme-feeling-blue.css │ ├── theme-flattop.css │ ├── theme-material.css │ ├── theme-monokai.css │ ├── theme-muted.css │ ├── theme-newspaper.css │ └── theme-outline.css └── views ├── documentation.blade.php └── issues.blade.php /.gitattributes: -------------------------------------------------------------------------------- 1 | *.css linguist-detectable=false 2 | *.php linguist-detectable=true -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: hussein4alaa 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: suggestions 6 | assignees: hussein4alaa 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | node_modules/ 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | # Laravel 4 specific 7 | bootstrap/compiled.php 8 | app/storage/ 9 | 10 | # Laravel 5 & Lumen specific 11 | public/storage 12 | public/hot 13 | 14 | # Laravel 5 & Lumen specific with changed public path 15 | public_html/storage 16 | public_html/hot 17 | 18 | storage/*.key 19 | .env 20 | Homestead.yaml 21 | Homestead.json 22 | /.vagrant 23 | .phpunit.result.cache 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Swagger Laravel Autogenerate Package 2 | 3 | Thank you for considering contributing to Swagger Laravel Autogenerate Package! :tada: 4 | 5 | ## How to Contribute 6 | 7 | If you have found a bug or have a feature request, please open an issue to discuss it. 8 | 9 | If you would like to contribute code, follow these steps: 10 | 11 | 1. Fork the repository and clone it to your local machine. 12 | 2. Create a new branch for your changes: `git checkout -b feature-name`. 13 | 3. Make your changes and test them thoroughly. 14 | 4. Commit your changes: `git commit -am 'Add new feature'`. 15 | 5. Push to your branch: `git push origin feature-name`. 16 | 6. Submit a pull request with a clear description of your changes. 17 | 18 | ## Development Setup 19 | 20 | To set up the development environment, follow these steps: 21 | 22 | 1. Read the README file to understand the installation process and configure any necessary environment variables. 23 | 24 | 25 | ## Code Style 26 | 27 | Please follow the coding standards and conventions used in the project. 28 | 29 | ## Questions or Need Help? 30 | 31 | If you have any questions or need assistance, feel free to open an issue or reach out to the maintainers. 32 | 33 | We appreciate your contributions to Swagger Laravel Autogenerate Package! :rocket: 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 HusseinAlaa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swagger Laravel Autogenerate Package 2 | 3 | The Swagger Laravel Autogenerate Package is a convenient tool that automatically generates Swagger documentation for your Laravel APIs based on your route definitions. It eliminates the need for manually documenting your API endpoints, saving you time and effort. 4 | 5 | 6 | 7 | ![Swagger Laravel Autogenerate Package](https://www.scottbrady91.com/img/logos/swagger-banner.png) 8 | 9 | 10 | ## Features 11 | 12 | - Automatically generates Swagger documentation for Laravel APIs. 13 | - Extracts route information, including URI, HTTP methods, route names, middleware, and more. 14 | - Supports request validations and parameter definitions. 15 | - Generates JSON output conforming to the Swagger/OpenAPI specification. 16 | - Easy integration and configuration within Laravel projects. 17 | 18 | 19 | ## Installation 20 | 21 | Install the Swagger Laravel Autogenerate Package via Composer: 22 | 23 | ``` 24 | composer require g4t/swagger 25 | ``` 26 | 27 | ## Usage 28 | 29 | #### Click here to watch a video on how to use this package 30 | [![Explanatory video on how to use](https://img.youtube.com/vi/bI1BY9tAwOw/0.jpg)](https://www.youtube.com/watch?v=bI1BY9tAwOw) 31 | 32 | 33 | 1. After installing the package, publish the configuration file: 34 | ``` 35 | php artisan vendor:publish --provider "G4T\Swagger\SwaggerServiceProvider" 36 | ``` 37 | 38 | 2. Configure the package by modifying the `config/swagger.php` file according to your needs. This file allows you to specify various settings for the Swagger documentation generation. 39 | 40 | 3. Access the generated Swagger documentation by visiting the `/swagger/documentation` route in your Laravel application. For example, `http://your-app-url/swagger/documentation`. 41 | 42 | 4. The issues history page is now included in config/swagger.php, and the default route is `http://your-app-url/swagger/issues`. 43 | 44 | 5. To add a description in a Swagger route using the ->description() method, you can follow the example you provided and include it in your Laravel application's routes. 45 | Here's how you can describe a route using the ->description() method in a Swagger route: 46 | ```php 47 | Route::get('user', [UserController::class, 'index'])->description('Get list of users with pagination.'); 48 | ``` 49 | 6. To add a summary in a Swagger route using the ->summary() method, you can follow the example you provided and include it in your Laravel application's routes. 50 | Here's how you can describe a route using the ->summary() method in a Swagger route: 51 | ```php 52 | Route::get('user', [UserController::class, 'index'])->summary('get users.'); 53 | ``` 54 | 7. To hide endpoint from Swagger documentation using the ->hiddenDoc() method. 55 | Here's how you can hide route using the ->hiddenDoc() method: 56 | ```php 57 | Route::get('user', [UserController::class, 'index'])->hiddenDoc(); 58 | ``` 59 | 8. To add a Section Description you can use this attribute `#[SwaggerSection('everything about your users')]` in your controller. 60 | Here's how you can use this attribute in your controller: 61 | ```php 62 | false, 79 | "username" => "admin", 80 | "password" => "pass", 81 | "sesson_ttl" => 100000, 82 | ``` 83 | 84 | ## Suggestions 85 | 86 | If you have any suggestions or feature requests, please feel free to add them on our [Canny board](https://g4t.canny.io/). 87 | 88 | 89 | 90 | ## Contributing 91 | 92 | Contributions to the Swagger Laravel Autogenerate Package are always welcome! If you find any issues or have suggestions for improvements, please feel free to open an issue or submit a pull request. 93 | 94 | 95 | ## License 96 | 97 | The Swagger Laravel Autogenerate Package is open-source software licensed under the [MIT license](LICENSE.md). 98 | 99 | ## Credits 100 | 101 | The Swagger Laravel Autogenerate Package is developed and maintained by [HusseinAlaa](https://www.linkedin.com/in/hussein4alaa/). 102 | 103 | ## Additional Resources 104 | 105 | - [Swagger Documentation](https://swagger.io/docs/) 106 | - [Laravel Documentation](https://laravel.com/docs) 107 | - [GitHub](https://github.com/hussein4alaa/laravel-g4t-swagger-auto-generate) 108 | 109 | 110 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Supported laravel versions 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 5.x | :white_check_mark: | 10 | | 6.x | :white_check_mark: | 11 | | 7.x | :white_check_mark: | 12 | | 8.x | :white_check_mark: | 13 | | 9.x | :white_check_mark: | 14 | | 10.x | :white_check_mark: | 15 | | 11.x | :white_check_mark: | 16 | 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "g4t/swagger", 3 | "description": "g4t laravel swagger", 4 | "autoload": { 5 | "psr-4": { 6 | "G4T\\Swagger\\": "src/" 7 | } 8 | }, 9 | "authors": [ 10 | { 11 | "name": "Hussein Alaa", 12 | "email": "hussein4alaa@gmail.com" 13 | } 14 | ], 15 | "license": "MIT", 16 | "minimum-stability": "stable", 17 | "require": {}, 18 | "extra": { 19 | "laravel": { 20 | "providers": [ 21 | "G4T\\Swagger\\SwaggerServiceProvider" 22 | ] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /i_stand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hussein4alaa/laravel-g4t-swagger-auto-generate/fcc51250541593bc21d5a5437db33d4b525d5188/i_stand.png -------------------------------------------------------------------------------- /src/Attributes/SwaggerSection.php: -------------------------------------------------------------------------------- 1 | value = $value; 15 | } 16 | 17 | public function getValue() 18 | { 19 | return $this->value; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Commands/GenerateDocsCommand.php: -------------------------------------------------------------------------------- 1 | info('Generating API documentation...'); 19 | $doc = new DocumentationController; 20 | $jsonData = $doc->getSwaggerData(); 21 | $filePath = public_path('doc.json'); 22 | file_put_contents($filePath, json_encode($jsonData, JSON_PRETTY_PRINT)); 23 | $this->info('API documentation generated successfully.'); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/Controllers/DocumentationController.php: -------------------------------------------------------------------------------- 1 | swagger(); 20 | return $response; 21 | } 22 | 23 | public function showViewDocumentation() 24 | { 25 | $response = $this->showJsonDocumentation(); 26 | $versions = $this->reformatVersions(); 27 | $themes = $this->getThemesList(); 28 | $themes_path = url('g4t/swagger/themes'); 29 | 30 | $stylesheet = config('swagger.stylesheet'); 31 | return view('swagger::documentation', [ 32 | 'themes_path' => $themes_path, 33 | 'response' => $response, 34 | 'versions' => $versions, 35 | 'stylesheet' => $stylesheet, 36 | 'themes' => $themes 37 | ]); 38 | } 39 | 40 | private function reformatVersions() 41 | { 42 | $config = config('swagger'); 43 | $versions = []; 44 | foreach ($config['versions'] as $version) { 45 | $versions[] = [ 46 | 'name' => $version, 47 | 'url' => url($config["url"] . "/json?version=$version") 48 | ]; 49 | } 50 | $data['versions'] = $versions; 51 | $data['default'] = $config['default']; 52 | return $data; 53 | } 54 | 55 | 56 | public function showJsonDocumentation() 57 | { 58 | $static_json = config('swagger.load_from_json'); 59 | if ($static_json) { 60 | $filePath = public_path('doc.json'); 61 | if (!file_exists($filePath)) { 62 | return []; 63 | } 64 | $jsonContent = file_get_contents($filePath); 65 | $data = json_decode($jsonContent, true); 66 | if (request()->filled('version')) { 67 | return $this->filter($data); 68 | } 69 | return $data; 70 | } else { 71 | $response = $this->getSwaggerData(); 72 | return response()->json($response); 73 | } 74 | } 75 | 76 | public function filter($data) 77 | { 78 | $searchTerm = request()->version; 79 | if ($searchTerm == 'all') { 80 | return $data; 81 | } 82 | 83 | $paths = []; 84 | $tags = []; 85 | foreach ($data['components']['paths'] as $key => $path) { 86 | if (str_contains($key, $searchTerm)) { 87 | $paths[$key] = $data['components']['paths'][$key]; 88 | foreach ($path as $path_key => $path_value) { 89 | $tags[] = $path_value['tags'][0]; 90 | } 91 | } 92 | } 93 | 94 | 95 | $data['components']['paths'] = $paths; 96 | $data['components']['tags'] = $tags; 97 | $data['tags'] = $tags; 98 | $data['paths'] = $paths; 99 | return $data; 100 | } 101 | 102 | public function getThemesList() 103 | { 104 | try { 105 | $directory = public_path('g4t/swagger/themes'); 106 | $files = File::files($directory); 107 | $fileNamesWithoutCss = []; 108 | $fileNamesWithoutCss[] = 'default'; 109 | foreach ($files as $file) { 110 | $fileName = pathinfo($file, PATHINFO_FILENAME); 111 | if (pathinfo($file, PATHINFO_EXTENSION) === 'css') { 112 | $fileNameWithoutCss = str_replace('.css', '', $fileName); 113 | $fileNamesWithoutCss[] = $fileNameWithoutCss; 114 | } 115 | } 116 | return $fileNamesWithoutCss; 117 | } catch (\Throwable $th) { 118 | $fileNamesWithoutCss[] = 'default'; 119 | return $fileNamesWithoutCss; 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Controllers/IssueController.php: -------------------------------------------------------------------------------- 1 | parseNewLogEntries($logContents); 16 | } 17 | $issues = array_reverse($issues); 18 | return view('swagger::issues', ['issues' => $issues]); 19 | } 20 | 21 | private function parseNewLogEntries($logContents) 22 | { 23 | $newEntries = []; 24 | $logLines = explode("\n", $logContents); 25 | foreach ($logLines as $line) { 26 | if (str_contains($line, 'g4t/swagger') && str_contains($line, 'local.')) { 27 | preg_match_all('/\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]/', $line, $matches); 28 | $newEntries[] = [ 29 | 'message' => $line, 30 | 'date' => isset($matches[1][0]) ? $matches[1][0] : "Unknwon" 31 | ]; 32 | } 33 | } 34 | return $newEntries; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Helpers.php: -------------------------------------------------------------------------------- 1 | middleware()); 30 | } 31 | 32 | 33 | public function getRouteName(string $route, string $prefix): string 34 | { 35 | $escapedPrefix = preg_quote($prefix, '/'); 36 | $regex = "/{$escapedPrefix}\/([^\/]+)/"; 37 | if (preg_match($regex, $route, $matches)) { 38 | return $matches[1]; 39 | } 40 | return 'unknown'; 41 | } 42 | 43 | 44 | public function generateOperationId(string $uri, string $method): string 45 | { 46 | $operationId = str_replace(['/', '[', ']'], '_', $uri) . '_' . $method; 47 | $operationId = str_replace(['{', '}'], '_', $operationId); 48 | 49 | return $operationId; 50 | } 51 | 52 | 53 | 54 | public function getRequestClassName(string $controllerMethod): array 55 | { 56 | if ($controllerMethod !== 'Closure') { 57 | $exploded = explode('@', $controllerMethod); 58 | 59 | if (!isset($exploded[0], $exploded[1])) { 60 | return []; 61 | } 62 | try { 63 | $class = $exploded[0]; 64 | if (isset($exploded[1])) { 65 | $method = $exploded[1]; 66 | } 67 | $reflection = new ReflectionMethod($class, $method); 68 | $parameters = $reflection->getParameters() ?? []; 69 | foreach ($parameters as $parameter) { 70 | $typeHint = $parameter ? $parameter->getType() : null; 71 | if ($typeHint instanceof ReflectionNamedType && !$typeHint->isBuiltin()) { 72 | try { 73 | $request = $typeHint->getName(); 74 | $request = new $request(); 75 | $rules = $request->rules(); 76 | return $this->confirmedValidation($rules); 77 | } catch (\Throwable $th) { 78 | } 79 | } 80 | } 81 | } catch (ReflectionException $e) { 82 | return []; 83 | } 84 | return []; 85 | } 86 | } 87 | 88 | 89 | private function confirmedValidation($rules) 90 | { 91 | if (str_contains(json_encode($rules), 'confirmed')) { 92 | foreach ($rules as $key => $rule) { 93 | if (str_contains($rule, 'confirmed')) { 94 | $rules["{$key}_confirmation"] = str_replace('confirmed', '', $rule); 95 | } 96 | } 97 | } 98 | return $rules; 99 | } 100 | 101 | 102 | public function schemaName(string $action): string 103 | { 104 | $className = class_basename($action); 105 | $className = str_replace('Controller', '', $className); 106 | $className = strstr($className, '@', true); 107 | $methodName = Str::afterLast($action, '@'); 108 | $modifiedClassName = Str::studly(ucfirst($className) . ucfirst($methodName)); 109 | return $modifiedClassName; 110 | } 111 | 112 | 113 | public function checkIfQueryParamRequiredOrNot($params) 114 | { 115 | $required = false; 116 | if (!is_array($params)) { 117 | $params = explode('|', $params); 118 | } 119 | foreach ($params as $param) { 120 | if ($param == 'required') { 121 | $required = true; 122 | break; 123 | } 124 | } 125 | return $required; 126 | } 127 | 128 | 129 | public function getInputName(string $string, int $number = 0): string 130 | { 131 | $name = preg_replace('/\.(\w+)/', '[$1]', $string); 132 | if (str_contains($name, '.*')) { 133 | return str_replace(".*", "[merge_input]", $name); 134 | } 135 | return $name; 136 | } 137 | 138 | 139 | public function formatParams($validations, $route) 140 | { 141 | $method = $route->methods(); 142 | $params_list = []; 143 | if ( 144 | in_array($method, ['PUT', 'put', 'Put', 'PUT|PATCH']) or 145 | is_array($method) && in_array('GET', $method) or 146 | in_array('GET|HEAD', $method) or 147 | in_array('DELETE', $method) or 148 | in_array('DELETE|HEAD', $method) 149 | ) { 150 | if (!is_null($validations)) { 151 | foreach ($validations as $key => $param) { 152 | $params_list[] = [ 153 | "name" => $this->getInputName($key), 154 | "in" => "query", 155 | "description" => $this->getInputName($key), 156 | "required" => $this->checkIfQueryParamRequiredOrNot($param), 157 | "schema" => $this->checkSchemaType($param) 158 | ]; 159 | } 160 | } 161 | } 162 | 163 | $required = $this->pathRequired($route); 164 | 165 | $params = $route->parameterNames(); 166 | foreach ($params as $param) { 167 | $params_list[] = [ 168 | "name" => $param, 169 | "in" => "path", 170 | "description" => $param, 171 | "required" => $required, 172 | "schema" => $this->checkSchemaType($param) 173 | ]; 174 | } 175 | return $params_list; 176 | } 177 | 178 | 179 | private function checkSchemaType($param) 180 | { 181 | if (is_string($param)) { 182 | return $this->getSwaggerInputSchema($param); 183 | } else { 184 | $param = $this->convertValidationToOneLine($param); 185 | return $this->getSwaggerInputSchema($param); 186 | } 187 | } 188 | 189 | 190 | 191 | public function pathRequired($route) 192 | { 193 | $required = true; 194 | if (strpos($route->uri, '?') !== false) { 195 | $required = false; 196 | } 197 | return $required; 198 | } 199 | 200 | public function checkIfTokenIsRequired($route) 201 | { 202 | $middlewares = $route->gatherMiddleware(); 203 | $authMiddlewares = config('swagger.auth_middlewares'); 204 | 205 | foreach ($middlewares as $middleware) { 206 | if (in_array($middleware, $authMiddlewares)) { 207 | return true; 208 | } 209 | } 210 | 211 | return false; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/Middleware/BasicAuthentication.php: -------------------------------------------------------------------------------- 1 | username = config('swagger.username'); 20 | $this->password = config('swagger.password'); 21 | $this->ttl = config('swagger.sesson_ttl'); 22 | $this->enable_auth = config('swagger.enable_auth'); 23 | } 24 | 25 | public function handle(Request $request, Closure $next) 26 | { 27 | if(!$this->enable_auth) { 28 | return $next($request); 29 | } 30 | 31 | $lastActivity = cache()->get('auth_last_activity'); 32 | if (cache()->has('auth_last_activity')) { 33 | $lastActivity = cache()->get('auth_last_activity'); 34 | if (time() - $lastActivity > $this->ttl) { 35 | cache()->forget('auth_user'); 36 | cache()->forget('auth_last_activity'); 37 | throw new HttpException(Response::HTTP_UNAUTHORIZED, 'Session expired.'); 38 | } 39 | } 40 | 41 | if (!$request->hasHeader('Authorization')) { 42 | header('WWW-Authenticate: Basic realm="HiBit"'); 43 | exit; 44 | } 45 | 46 | $credentials = base64_decode(substr($request->header('Authorization'), 6)); 47 | [$username, $password] = explode(':', $credentials); 48 | 49 | if ($username !== $this->username || $password !== $this->password) { 50 | throw new HttpException(Response::HTTP_UNAUTHORIZED, 'Invalid credentials.'); 51 | } 52 | 53 | cache()->put('auth_user', $username); 54 | cache()->set('auth_last_activity', time()); 55 | 56 | return $next($request); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Middleware/SetJsonResponseMiddleware.php: -------------------------------------------------------------------------------- 1 | ["description" => "Successful operation"], 12 | "404" => ["description" => "{$route['name']} not found"], 13 | "405" => ["description" => "Validation exception"] 14 | ]; 15 | } 16 | 17 | private static function getSummary($route) 18 | { 19 | return !is_null($route['summary']) ? $route['summary'] : $route['name']; 20 | } 21 | 22 | protected static function addResponseExamples(&$response, $route) 23 | { 24 | $enable_response_schema = config('swagger.enable_response_schema'); 25 | if ($enable_response_schema) { 26 | $dir = str_replace(['/', '{', '}', '?'], '-', $route['uri']); 27 | $jsonDirPath = storage_path("swagger/{$route['controller']}/{$dir}"); 28 | if (is_dir($jsonDirPath)) { 29 | $files = glob($jsonDirPath . '/*.json'); 30 | foreach ($files as $file) { 31 | $parts = explode('/', rtrim($file, '/')); 32 | $lastPart = end($parts); 33 | if (preg_match('/(\d+)\.json$/', $lastPart, $matches)) { 34 | $statusCode = $matches[1]; 35 | $jsonContent = json_decode(file_get_contents($file), true); 36 | $response["responses"]["$statusCode"]["description"] = $jsonContent['status_text']; 37 | $response["responses"]["$statusCode"]["content"]["application/json"]["example"] = $jsonContent['response']; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | public static function index($route) 45 | { 46 | $response = [ 47 | "tags" => [$route['controller']], 48 | "summary" => self::getSummary($route), 49 | "description" => "{$route['description']}", 50 | "operationId" => $route['operation_id'], 51 | "parameters" => $route['params'], 52 | "responses" => self::getResponses(static::METHOD, $route), 53 | "security" => self::getSecurity($route) 54 | ]; 55 | 56 | // Add requestBody if schema is available 57 | if ($route['has_schema']) { 58 | $response['requestBody'] = [ 59 | "description" => "{$route['description']}", 60 | "content" => [ 61 | "multipart/form-data" => [ 62 | "schema" => [ 63 | '$ref' => "#/components/schemas/{$route['schema_name']}" 64 | ] 65 | ], 66 | "application/json" => [ 67 | "schema" => [ 68 | '$ref' => "#/components/schemas/{$route['schema_name']}" 69 | ] 70 | ], 71 | ], 72 | "required" => true 73 | ]; 74 | } 75 | 76 | $enable_response_schema = config('swagger.enable_response_schema'); 77 | if ($enable_response_schema) { 78 | $dir = str_replace(['/', '{', '}', '?'], '-', $route['uri']); 79 | $jsonDirPath = storage_path("swagger/{$route['controller']}/{$dir}"); 80 | if (is_dir($jsonDirPath)) { 81 | $files = glob($jsonDirPath . '/*.json'); 82 | foreach ($files as $file) { 83 | $parts = explode('/', rtrim($file, '/')); 84 | $lastPart = end($parts); 85 | if (preg_match('/(\d+)\.json$/', $lastPart, $matches)) { 86 | $statusCode = $matches[1]; 87 | $jsonContent = json_decode(file_get_contents($file), true); 88 | $response["responses"]["$statusCode"]["description"] = $jsonContent['status_text']; 89 | $response["responses"]["$statusCode"]["content"]["application/json"]["example"] = $jsonContent['response']; 90 | } 91 | } 92 | } 93 | } 94 | 95 | if ($route['need_token']) { 96 | $security_array = []; 97 | $security_schemes = config('swagger.security_schemes'); 98 | foreach ($security_schemes as $key => $security_scheme) { 99 | $security_array[] = [$key => []]; 100 | } 101 | $response['security'] = $security_array; 102 | } else { 103 | unset($response['security']); 104 | } 105 | 106 | return $response; 107 | } 108 | 109 | protected static function getSecurity($route) 110 | { 111 | if ($route['need_token']) { 112 | $security_array = []; 113 | $security_schemes = config('swagger.security_schemes'); 114 | foreach ($security_schemes as $key => $security_scheme) { 115 | $security_array[] = [$key => []]; 116 | } 117 | return $security_array; 118 | } 119 | return []; 120 | } 121 | } -------------------------------------------------------------------------------- /src/Responses/DeleteResponse.php: -------------------------------------------------------------------------------- 1 | group(function () use ($url, $issues_url) { 12 | Route::get("/$url", [DocumentationController::class, "showViewDocumentation"]); 13 | Route::get("/$url/json", [DocumentationController::class, "showJsonDocumentation"])->name("swagger.json"); 14 | Route::get("/$issues_url", [IssueController::class, "index"]); 15 | }); -------------------------------------------------------------------------------- /src/Sections/Paths.php: -------------------------------------------------------------------------------- 1 | generateSchemaNested($validations, $name, $method); 15 | } else { 16 | $schema = $this->generateGenericSchema($validations, $name, $method); 17 | } 18 | 19 | return $schema; 20 | } 21 | 22 | 23 | public function defaultSchemaFormat(string $name): array 24 | { 25 | return [ 26 | "required" => [], 27 | "type" => "object", 28 | "properties" => [], 29 | "xml" => [ 30 | "name" => Str::lower($name) 31 | ] 32 | ]; 33 | } 34 | 35 | 36 | protected function generateGenericSchema(array $validations, string $name, string $method): array 37 | { 38 | $schemas = $this->defaultSchemaFormat($name); 39 | if (is_null($validations)) { 40 | return $schemas; 41 | } 42 | [$validation_content, $required] = $this->generateGenericRequiredAndRules($validations, $method); 43 | 44 | 45 | $schemas["required"] = $required; 46 | foreach ($validation_content as $column_name => $validation_value) { 47 | if (!str_contains($column_name, "[merge_input]")) { 48 | $name = $this->getInputName($column_name); 49 | if (str_contains($validation_value, "array")) { 50 | $schemas['properties'][$name . "[]"] = $this->getSwaggerInputSchema($validation_value); 51 | } else { 52 | $schemas['properties'][$name] = $this->getSwaggerInputSchema($validation_value); 53 | } 54 | } 55 | } 56 | return $schemas; 57 | } 58 | 59 | 60 | protected function generateSchemaNested($validations, $name, $method) 61 | { 62 | $schemas = $this->defaultSchemaFormat($name); 63 | if (is_null($validations)) { 64 | return $schemas; 65 | } 66 | 67 | [$validation_content, $required] = $this->generateGenericRequiredAndRules($validations, $method); 68 | $schemas["required"] = $required; 69 | foreach ($validation_content as $column_name => $validation_value) { 70 | if (strpos($column_name, '.') !== false && !str_contains($column_name, ".*")) { 71 | $this->addNestedProperty($schemas["properties"], $column_name, $validation_value); 72 | } else { 73 | if (!str_contains($column_name, "[merge_input]")) { 74 | $name = $this->getInputName($column_name); 75 | if (str_contains($validation_value, "array")) { 76 | $schemas['properties'][$name . "[]"] = $this->getSwaggerInputSchema($validation_value); 77 | } else { 78 | $schemas['properties'][$name] = $this->getSwaggerInputSchema($validation_value); 79 | } 80 | } 81 | } 82 | } 83 | return $schemas; 84 | } 85 | 86 | 87 | public function convertValidationToOneLine(array $validation): string 88 | { 89 | $formated_validation = ''; 90 | $count = count($validation); 91 | foreach ($validation as $key => $format_validation) { 92 | if (is_string($format_validation)) { 93 | if ($count - 1 == $key) { 94 | $formated_validation .= $format_validation; 95 | } else { 96 | $formated_validation .= $format_validation . "|"; 97 | } 98 | } else { 99 | try { 100 | $reflection = new ReflectionClass($format_validation); 101 | $property = $reflection->getProperty('type'); 102 | $property->setAccessible(true); 103 | $enumClass = $property->getValue($format_validation); 104 | $is_enum = $this->isEnum($enumClass); 105 | if($is_enum) { 106 | $formated_validation .= $this->getCasesFromEnum($enumClass); 107 | } 108 | } catch (\Throwable $th) { 109 | 110 | } 111 | } 112 | } 113 | return $formated_validation; 114 | } 115 | 116 | 117 | private function getCasesFromEnum($class) 118 | { 119 | $reflection = new ReflectionClass($class); 120 | $cases = $reflection->getReflectionConstants(); 121 | $caseList = 'in:'; 122 | foreach ($cases as $case) { 123 | $caseList .= $case->getValue()->value.","; 124 | } 125 | if (substr($caseList, -1) === ',') { 126 | $caseList = substr($caseList, 0, -1); 127 | } 128 | return $caseList; 129 | 130 | } 131 | 132 | 133 | private function isEnum($className) { 134 | $reflection = new ReflectionClass($className); 135 | return $reflection->isEnum(); 136 | } 137 | 138 | 139 | 140 | public function generateGenericRequiredAndRules(array $validations, string $method): array 141 | { 142 | $rules = []; 143 | $required = []; 144 | 145 | foreach ($validations as $key => $validation) { 146 | $rule_key = $key; 147 | if (is_array($validation)) { 148 | $rules[$rule_key] = $this->convertValidationToOneLine($validation); 149 | } else { 150 | if (str_contains($validation, 'image') || str_contains($validation, 'file') || str_contains($validation, 'mimes')) { 151 | $rule_key = $this->getInputName($key); 152 | } 153 | $rules[$rule_key] = $validation; 154 | } 155 | if (str_contains($rule_key, "[merge_input]")) { 156 | $new_key_for_merge = str_replace('[merge_input]', '', $rule_key); 157 | foreach ($validations as $merge_key => $merge_validation) { 158 | $merge_name = $this->getInputName($merge_key); 159 | if ($merge_name == $new_key_for_merge) { 160 | $response = implode('|', array_unique(array_filter(explode('|', $merge_validation . '|' . $validation)))); 161 | $rules[$merge_name] = $response; 162 | } 163 | } 164 | } 165 | 166 | 167 | if (str_contains($rules[$rule_key], "required")) { 168 | if (str_contains($rules[$rule_key], "array")) { 169 | $required[] = $rule_key . "[]"; 170 | } else { 171 | if (!str_contains($rule_key, "merge_input")) { 172 | $required[] = $rule_key; 173 | } 174 | } 175 | } 176 | 177 | } 178 | $string_rules = json_encode($rules); 179 | if ($method == 'PUT' && (str_contains($string_rules, 'image') || str_contains($string_rules, 'file') || str_contains($string_rules, 'mimes'))) { 180 | $method_rule = ["_method" => "required|in:PUT"]; 181 | $rules = array_merge($rules, $method_rule); 182 | } 183 | return [$rules, $required]; 184 | } 185 | 186 | 187 | 188 | 189 | public function getValidationDefaultType($key_name) 190 | { 191 | $type = 'object'; 192 | if (substr_count($key_name, '.') === 0) { 193 | $type = 'string'; 194 | } 195 | return $type; 196 | } 197 | 198 | 199 | public function convertValidationsFromArrayToString($validation) 200 | { 201 | $formated_validation = ''; 202 | if (is_array($validation)) { 203 | $count = count($validation); 204 | foreach ($validation as $key => $format_validation) { 205 | if ($count - 1 == $key) { 206 | $formated_validation .= $format_validation; 207 | } else { 208 | $formated_validation .= $format_validation . "|"; 209 | } 210 | } 211 | } else { 212 | $formated_validation = $validation; 213 | } 214 | return $formated_validation; 215 | } 216 | 217 | 218 | protected function addNestedProperty(&$properties, $key, $validation) 219 | { 220 | $keys = explode('.', $key); 221 | $current = &$properties; 222 | 223 | foreach ($keys as $index => $nestedKey) { 224 | if (!isset($current[$nestedKey])) { 225 | $type = 'object'; 226 | 227 | if ($index === count($keys) - 1) { 228 | $type = 'string'; 229 | } 230 | 231 | $current[$nestedKey] = [ 232 | 'type' => $type, 233 | 'properties' => [] 234 | ]; 235 | } 236 | 237 | $current = &$current[$nestedKey]['properties']; 238 | } 239 | 240 | $current = $this->getSwaggerInputSchema($validation); 241 | } 242 | 243 | public function setColumnAttributes(string $validation_value, string $condition, string $key, string $value): array 244 | { 245 | $schema = []; 246 | if (str_contains($validation_value, $condition)) { 247 | $schema[$key] = $value; 248 | } 249 | return $schema; 250 | } 251 | 252 | public function setCustomColumnAttributes(string $validation_value, string $condition, string $key): array 253 | { 254 | $schema = []; 255 | preg_match('/' . $condition . '\:([^|]+)/', $validation_value, $matches); 256 | if (isset($matches[1])) { 257 | $schema[$key] = $matches[1]; 258 | } 259 | return $schema; 260 | } 261 | 262 | public function setEnumColumnAttributes(string $validation_value, string $condition, string $key): array 263 | { 264 | $schema = []; 265 | if (str_contains($validation_value, "min")) { 266 | return $schema; 267 | } 268 | $data = $this->setCustomColumnAttributes($validation_value, $condition, $key); 269 | if (isset($data[$key])) { 270 | $schema[$key] = explode(',', $data[$key]); 271 | } 272 | return $schema; 273 | } 274 | 275 | 276 | public function setExistsColumnAttributes(string $validation_value, string $condition, string $key): array 277 | { 278 | $schema = []; 279 | $data = $this->setCustomColumnAttributes($validation_value, $condition, $key); 280 | if (isset($data[$key])) { 281 | [$table, $column] = explode(',', $data[$key]); 282 | $schema[$key] = $this->getExistsData($table, $column); 283 | } 284 | return $schema; 285 | } 286 | 287 | public function getExistsData(string $table, string $column): array 288 | { 289 | try { 290 | return DB::table($table)->pluck($column)->toArray(); 291 | } catch (\Throwable $th) { 292 | return [ 293 | "Error: Check Database connection" 294 | ]; 295 | } 296 | } 297 | 298 | public function setArrayOfInputsAttributes() 299 | { 300 | $schema['type'] = 'array'; 301 | $schema['items'] = [ 302 | "type" => "string", 303 | "format" => "binary" 304 | ]; 305 | return $schema; 306 | } 307 | 308 | 309 | public function getSwaggerInputSchema(string $validation_value, $type = 'string') 310 | { 311 | $schema = []; 312 | $image_format = []; 313 | $file_format = []; 314 | $mimes_format = []; 315 | $array_of_inputs = []; 316 | $nullable = []; 317 | $required = $this->setColumnAttributes($validation_value, 'required', 'required', 'true'); 318 | if (!$required) { 319 | $nullable = $this->setColumnAttributes($validation_value, 'nullable', 'nullable', 'true'); 320 | } 321 | $string = $this->setColumnAttributes($validation_value, 'string', 'type', 'string'); 322 | $integer = $this->setColumnAttributes($validation_value, 'integer', 'type', 'number'); 323 | $numeric = $this->setColumnAttributes($validation_value, 'numeric', 'type', 'number'); 324 | $uuid_type = $this->setColumnAttributes($validation_value, 'uuid', 'type', 'string'); 325 | $uuid_format = $this->setColumnAttributes($validation_value, 'uuid', 'format', 'uuid'); 326 | $boolean = $this->setColumnAttributes($validation_value, 'boolean', 'type', 'boolean'); 327 | $date_type = $this->setColumnAttributes($validation_value, 'date', 'type', 'string'); 328 | $date_format = $this->setColumnAttributes($validation_value, 'date', 'format', 'date'); 329 | $array = $this->setColumnAttributes($validation_value, 'array', 'type', 'array'); 330 | $email = $this->setColumnAttributes($validation_value, 'email', 'format', 'email'); 331 | $image_type = $this->setColumnAttributes($validation_value, 'image', 'type', 'string'); 332 | $minimum = $this->setCustomColumnAttributes($validation_value, 'min', 'minimum'); 333 | $maximum = $this->setCustomColumnAttributes($validation_value, 'max', 'maximum'); 334 | $type = $this->setColumnAttributes($validation_value, 'type', 'type', 'string'); 335 | $file_type = $this->setColumnAttributes($validation_value, 'file', 'type', 'string'); 336 | $mimes_type = $this->setColumnAttributes($validation_value, 'mimes', 'type', 'string'); 337 | $mimes_description = $this->setCustomColumnAttributes($validation_value, 'mimes', 'description'); 338 | $unique = $this->setColumnAttributes($validation_value, 'unique', 'unique', 'true'); 339 | $enum = $this->setEnumColumnAttributes($validation_value, 'in', 'enum'); 340 | if ($array && ($file_type || $mimes_type || $image_type)) { 341 | $array_of_inputs = $this->setArrayOfInputsAttributes(); 342 | } else { 343 | $image_format = $this->setColumnAttributes($validation_value, 'image', 'format', 'binary'); 344 | $file_format = $this->setColumnAttributes($validation_value, 'file', 'format', 'binary'); 345 | $mimes_format = $this->setColumnAttributes($validation_value, 'mimes', 'format', 'binary'); 346 | } 347 | $schema = array_merge( 348 | $required, 349 | $nullable, 350 | $string, 351 | $integer, 352 | $numeric, 353 | $uuid_type, 354 | $uuid_format, 355 | $boolean, 356 | $date_type, 357 | $date_format, 358 | $array, 359 | $email, 360 | $image_type, 361 | $image_format, 362 | $minimum, 363 | $maximum, 364 | $type, 365 | $file_type, 366 | $file_format, 367 | $mimes_type, 368 | $mimes_format, 369 | $mimes_description, 370 | $unique, 371 | $enum, 372 | $array_of_inputs, 373 | $schema, 374 | ); 375 | if(!isset($schema['type'])) { 376 | $schema['type'] = 'string'; 377 | } 378 | return $schema; 379 | } 380 | 381 | 382 | 383 | public function isRequiredRule($rule) 384 | { 385 | $required = false; 386 | if (str_contains($rule, "required")) { 387 | $required = true; 388 | } 389 | return $required; 390 | } 391 | } 392 | -------------------------------------------------------------------------------- /src/Sections/Tags.php: -------------------------------------------------------------------------------- 1 | $controller['name'], 13 | 'description' => $controller['description'] 14 | ]; 15 | } 16 | return $tags; 17 | } 18 | 19 | 20 | } -------------------------------------------------------------------------------- /src/Swagger.php: -------------------------------------------------------------------------------- 1 | "3.0.3", 26 | "info" => [ 27 | "title" => config('swagger.title'), 28 | "description" => config('swagger.description'), 29 | "termsOfService" => "http://swagger.io/terms/", 30 | "contact" => [ 31 | "email" => config('swagger.email'), 32 | ], 33 | "license" => [ 34 | "name" => "Github", 35 | "url" => "https://github.com/hussein4alaa" 36 | ], 37 | "version" => config('swagger.version') 38 | ], 39 | "servers" => config('swagger.servers'), 40 | "components" => $this->generateSwaggerJsonResponse(), 41 | "tags" => $this->generateSwaggerJsonResponse()->tags, 42 | "paths" => $this->generateSwaggerJsonResponse()->paths, 43 | ]; 44 | } 45 | 46 | 47 | 48 | /** 49 | * Generate the Swagger JSON response for API documentation. 50 | * 51 | * This function retrieves all routes defined in the application and filters out the API routes. It collects relevant information for each API route, including prefix, action name, route name, HTTP method, URI, operation ID, validations, and schema name. The function determines if a route has a schema based on the presence of validations. It also checks if a token is required for the route. 52 | * 53 | * The collected information is used to build an array of API routes, which includes details such as the route's prefix, method, URI, name, schema name, action, middleware, validations, parameters, operation ID, whether it has a schema, and whether a token is required. 54 | * 55 | * Additionally, the function collects all the route names to generate tags for the Swagger documentation. It formats the collected API routes and constructs the JSON data structure required for Swagger documentation. This JSON data includes tags, paths, schemas, and security schemes. 56 | * 57 | * The function returns the generated Swagger JSON response as an object. 58 | * 59 | * @return object The Swagger JSON response for API documentation. 60 | */ 61 | 62 | public function generateSwaggerJsonResponse() { 63 | $routes = Route::getRoutes(); 64 | $apiRoutes = []; 65 | $names = []; 66 | $schemas = []; 67 | $show_prefix_array = config('swagger.show_prefix'); 68 | $mapping_prefix = config('swagger.mapping_prefix'); 69 | $controllers = []; 70 | 71 | $version = $this->getVersion(); 72 | foreach ($routes as $route) { 73 | $filter_route = $this->isApiRoute($route); 74 | 75 | if (config('swagger.include_web_routes')) 76 | $filter_route = str_contains($route->getActionName(), 'App\\Http\\Controllers'); 77 | 78 | if ($filter_route) { 79 | if (is_string($route->getAction('controller'))) { 80 | $uri = '/' . $route->uri(); 81 | if (is_null($version) || str_contains($uri, $version)) { 82 | $prefix = $route->getPrefix(); 83 | $action = ltrim($route->getActionName(), '\\'); 84 | $controller = $this->getControllerName($route->getAction('controller')); 85 | $routeName = $this->getRouteName($route->uri(), $prefix); 86 | $method = implode('|', $route->methods()); 87 | $operationId = $this->generateOperationId($uri, $method); 88 | $validations = $this->getRequestClassName($action); 89 | $schemaName = $this->schemaName($action); 90 | if ($action !== 'Closure') { 91 | $description = isset($route->action['description']) ? $route->action['description'] : ''; 92 | $summary = isset($route->action['summary']) ? $route->action['summary'] : null; 93 | $is_hidden = isset($route->action['is_hidden']) ? $route->action['is_hidden'] : false; 94 | if($is_hidden) { 95 | continue; 96 | } 97 | $prefix_for_condition = isset($show_prefix_array) && count($show_prefix_array) > 0 ? $show_prefix_array : ["$prefix"]; 98 | if (in_array($prefix, $prefix_for_condition)) { 99 | $hasSchema = false; 100 | 101 | if (isset($mapping_prefix[$prefix])) { 102 | $uri = str_replace($prefix, $mapping_prefix[$prefix], $uri); 103 | $prefix = $mapping_prefix[$prefix]; 104 | } 105 | 106 | if (!is_null($validations) && count($validations) > 0) { 107 | $accept_methods = ['PUT', 'POST', 'PATCH']; 108 | if(in_array($method, $accept_methods)) { 109 | $hasSchema = true; 110 | $schemas[$schemaName] = $this->getSchemas($validations, $schemaName, $method); 111 | } 112 | } 113 | 114 | $needToken = $this->checkIfTokenIsRequired($route); 115 | $controller_path = $this->getControllerPath($route->getAction('controller')); 116 | $controller_description = $this->getSectionAttributeValue($controller_path); 117 | $controllers[$controller] = [ 118 | "name" => $controller, 119 | "class" => $controller_path, 120 | "description" => $controller_description 121 | ]; 122 | 123 | $params = $this->formatParams($validations, $route); 124 | 125 | $this->spatieSchema($params, $method); 126 | 127 | $apiRoutes[] = [ 128 | 'prefix' => $prefix, 129 | 'method' => $method, 130 | 'controller' => $controller, 131 | 'uri' => $uri, 132 | 'description' => $description, 133 | 'summary' => $summary, 134 | 'name' => $routeName, 135 | 'schema_name' => $schemaName, 136 | 'action' => $action, 137 | 'middleware' => $route->middleware(), 138 | 'validations' => $validations, 139 | 'params' => $params, 140 | 'operation_id' => $operationId, 141 | 'has_schema' => $hasSchema, 142 | 'need_token' => $needToken 143 | ]; 144 | } 145 | } 146 | } 147 | } 148 | } 149 | } 150 | $swaggerJson = new stdClass(); 151 | $swaggerJson->tags = $this->getTags($controllers); 152 | $swaggerJson->paths = $this->formatPaths($apiRoutes); 153 | $swaggerJson->schemas = $schemas; 154 | $swaggerJson->securitySchemes = config('swagger.security_schemes'); 155 | 156 | return $swaggerJson; 157 | } 158 | 159 | 160 | public function getControllerPath($controller) { 161 | try { 162 | $controller = explode("@", $controller); 163 | return $controller[0]; 164 | } catch (\Throwable $th) { 165 | return null; 166 | } 167 | } 168 | 169 | private function getSectionAttributeValue(string $controllerClassName) { 170 | try { 171 | $class = new $controllerClassName; 172 | $reflector = new ReflectionClass($class); 173 | $attributes = $reflector->getAttributes(SwaggerSection::class); 174 | if (!empty($attributes)) { 175 | $attribute = $attributes[0]; 176 | return $attribute->newInstance()->getValue(); 177 | } else { 178 | return null; 179 | } 180 | } catch (\Throwable $th) { 181 | return null; 182 | } 183 | } 184 | 185 | private function getVersion() { 186 | $versions = config('swagger.versions'); 187 | $version = 'api/'; 188 | if (request()->filled('version') && in_array(request()->version, $versions)) { 189 | if (request()->version == 'all') { 190 | $version = null; 191 | } else { 192 | $version = 'api/' . request()->version; 193 | } 194 | } 195 | return $version; 196 | } 197 | 198 | 199 | private function spatieSchema(&$params, $method) 200 | { 201 | $spatie_query_builder = config('swagger.spatie_query_builder'); 202 | if ($method == 'GET|HEAD' && $spatie_query_builder) { 203 | $params[] = [ 204 | "name" => "filter", 205 | "in" => "query", 206 | "description" => "Filter", 207 | "required" => false, 208 | "style" => "deepObject", 209 | "explode" => true, 210 | "schema" => [ 211 | "type" => "object", 212 | "additionalProperties" => [ 213 | "type" => "string", 214 | "description" => "The dynamic filtering" 215 | ] 216 | ] 217 | ]; 218 | $params[] = [ 219 | "name" => "sort", 220 | "in" => "query", 221 | "description" => "sort", 222 | "required" => false, 223 | "schema" => [ 224 | "nullable" => "true", 225 | "type" => "string", 226 | ] 227 | ]; 228 | $params[] = [ 229 | "name" => "include", 230 | "in" => "query", 231 | "description" => "include", 232 | "required" => false, 233 | "schema" => [ 234 | "nullable" => "true", 235 | "type" => "string", 236 | ] 237 | ]; 238 | } 239 | } 240 | 241 | } 242 | -------------------------------------------------------------------------------- /src/SwaggerServiceProvider.php: -------------------------------------------------------------------------------- 1 | action['description'] = $description; 22 | return $this; 23 | }); 24 | 25 | Route::macro('summary', function ($summary) { 26 | $this->action['summary'] = $summary; 27 | return $this; 28 | }); 29 | 30 | Route::macro('hiddenDoc', function () { 31 | $this->action['is_hidden'] = true; 32 | return $this; 33 | }); 34 | 35 | $this->publishes([ 36 | __DIR__ . '/config/swagger.php' => base_path('config/swagger.php'), 37 | ]); 38 | 39 | $this->publishes([ 40 | __DIR__.'/custom-assets' => public_path('g4t/swagger'), 41 | ], 'public'); 42 | 43 | $this->commands([ 44 | GenerateDocsCommand::class, 45 | ]); 46 | 47 | 48 | } 49 | 50 | /** 51 | * Bootstrap services. 52 | * 53 | * @return void 54 | */ 55 | public function boot() 56 | { 57 | $this->loadRoutesFrom(__DIR__.'/Routes/web.php'); 58 | $this->loadViewsFrom(__DIR__.'/views', 'swagger'); 59 | 60 | } 61 | } -------------------------------------------------------------------------------- /src/config/swagger.php: -------------------------------------------------------------------------------- 1 | env("SWAGGER_TITLE", "Api Documentation"), 13 | 14 | /* 15 | |-------------------------------------------------------------------------- 16 | | API Description 17 | |-------------------------------------------------------------------------- 18 | | 19 | | The description of your API. 20 | | 21 | */ 22 | "description" => env("SWAGGER_DESCRIPTION", "Laravel autogenerate swagger"), 23 | 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | API Email 27 | |-------------------------------------------------------------------------- 28 | | 29 | | The email associated with your API documentation. 30 | | 31 | */ 32 | "email" => env("SWAGGER_EMAIL", "hussein4alaa@gmail.com"), 33 | 34 | /* 35 | |-------------------------------------------------------------------------- 36 | | API Version 37 | |-------------------------------------------------------------------------- 38 | | 39 | | The version of your API. 40 | | 41 | */ 42 | "version" => env("SWAGGER_VERSION", "3.0.7"), 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Documentation Auth 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This options to enable documentation auth 50 | | 51 | */ 52 | "enable_auth" => false, 53 | "username" => "admin", 54 | "password" => "pass", 55 | "sesson_ttl" => 100000, 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Enable Response Schema 60 | |-------------------------------------------------------------------------- 61 | | 62 | | Whether to enable response schema or not. 63 | | 64 | */ 65 | "enable_response_schema" => true, 66 | 67 | "suggestions_select_input" => false, 68 | 69 | "load_from_json" => false, 70 | 71 | /* 72 | |-------------------------------------------------------------------------- 73 | | Authentication Middlewares 74 | |-------------------------------------------------------------------------- 75 | | 76 | | List of middleware names used for authentication. 77 | | 78 | */ 79 | "auth_middlewares" => [ 80 | "auth", 81 | "auth:api", 82 | ], 83 | 84 | /* 85 | |-------------------------------------------------------------------------- 86 | | API URL 87 | |-------------------------------------------------------------------------- 88 | | 89 | | The URL path for accessing your API documentation. 90 | | 91 | */ 92 | "url" => env("SWAGGER_URL", "swagger/documentation"), 93 | 94 | /* 95 | |-------------------------------------------------------------------------- 96 | | Issues URL 97 | |-------------------------------------------------------------------------- 98 | | 99 | | The URL path for accessing issues related to your API documentation. 100 | | 101 | */ 102 | "issues_url" => env("SWAGGER_ISSUE_URL", "swagger/issues"), 103 | 104 | /* 105 | |-------------------------------------------------------------------------- 106 | | Enable Swagger 107 | |-------------------------------------------------------------------------- 108 | | 109 | | Whether Swagger is enabled or not. 110 | | 111 | */ 112 | "enable" => env('SWAGGER_ENABLED', true), 113 | 114 | /* 115 | |-------------------------------------------------------------------------- 116 | | Show Prefix 117 | |-------------------------------------------------------------------------- 118 | | 119 | | List of prefixes to show in Swagger. 120 | | 121 | */ 122 | "show_prefix" => [], 123 | 124 | /* 125 | |-------------------------------------------------------------------------- 126 | | Include Web Routes 127 | |-------------------------------------------------------------------------- 128 | | 129 | | If you want to includes web.php routes, then enable this 130 | | 131 | */ 132 | "include_web_routes" => env('SWAGGER_INCLUDE_WEB_ROUTES', false), 133 | 134 | 135 | /* 136 | |-------------------------------------------------------------------------- 137 | | API Versions 138 | |-------------------------------------------------------------------------- 139 | | 140 | | List of versions to show in Swagger. 141 | | 142 | */ 143 | "versions" => [ 144 | "all", 145 | // "v1" 146 | ], 147 | 148 | "default" => "all", 149 | 150 | 151 | /* 152 | |-------------------------------------------------------------------------- 153 | | Servers 154 | |-------------------------------------------------------------------------- 155 | | 156 | | List of servers associated with your API. 157 | | 158 | */ 159 | "servers" => [ 160 | [ 161 | "url" => env("APP_URL"), 162 | "description" => "localhost" 163 | ] 164 | ], 165 | 166 | 167 | /* 168 | |-------------------------------------------------------------------------- 169 | | Security Schemes 170 | |-------------------------------------------------------------------------- 171 | | 172 | | Security schemes used in your API. 173 | | 174 | */ 175 | "security_schemes" => [ 176 | "authorization" => [ 177 | "type" => "apiKey", 178 | "name" => "authorization", 179 | "in" => "header" 180 | ], 181 | "apiKey1" => [ 182 | "type" => "apiKey", 183 | "name" => "key1", 184 | "in" => "query" 185 | ] 186 | ], 187 | 188 | /* 189 | |-------------------------------------------------------------------------- 190 | | Spatie Query Builder 191 | |-------------------------------------------------------------------------- 192 | | 193 | | Enable it if you using Spatie query builder package to add spatie filters in all GET routes. 194 | | 195 | */ 196 | "spatie_query_builder" => false, 197 | 198 | 199 | /* 200 | |-------------------------------------------------------------------------- 201 | | Status 202 | |-------------------------------------------------------------------------- 203 | | 204 | | HTTP response statuses for various methods. 205 | | 206 | */ 207 | "status" => [ 208 | "GET" => [ 209 | "200" => [ 210 | "description" => "Successful Operation", 211 | ], 212 | "404" => [ 213 | "description" => "Not Found" 214 | ] 215 | ], 216 | "POST" => [ 217 | "200" => [ 218 | "description" => "Successful Operation", 219 | ], 220 | "422" => [ 221 | "description" => "Validation Issues" 222 | ] 223 | ], 224 | "PUT" => [ 225 | "200" => [ 226 | "description" => "Successful Operation", 227 | ], 228 | "404" => [ 229 | "description" => "Not Found" 230 | ], 231 | "405" => [ 232 | "description" => "Validation exception" 233 | ] 234 | ], 235 | "PATCH" => [ 236 | "200" => [ 237 | "description" => "Successful Operation", 238 | ], 239 | "404" => [ 240 | "description" => "Not Found" 241 | ], 242 | "405" => [ 243 | "description" => "Validation exception" 244 | ] 245 | ], 246 | "DELETE" => [ 247 | "200" => [ 248 | "description" => "successful Operation", 249 | ], 250 | "404" => [ 251 | "description" => "page Not Found" 252 | ] 253 | ], 254 | ], 255 | 256 | ]; 257 | -------------------------------------------------------------------------------- /src/custom-assets/images/swagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hussein4alaa/laravel-g4t-swagger-auto-generate/fcc51250541593bc21d5a5437db33d4b525d5188/src/custom-assets/images/swagger.png -------------------------------------------------------------------------------- /src/custom-assets/images/theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hussein4alaa/laravel-g4t-swagger-auto-generate/fcc51250541593bc21d5a5437db33d4b525d5188/src/custom-assets/images/theme.png -------------------------------------------------------------------------------- /src/custom-assets/js/js-yaml.min.js: -------------------------------------------------------------------------------- 1 | /*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ 2 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).jsyaml={})}(this,(function(e){"use strict";function t(e){return null==e}var n={isNothing:t,isObject:function(e){return"object"==typeof e&&null!==e},toArray:function(e){return Array.isArray(e)?e:t(e)?[]:[e]},repeat:function(e,t){var n,i="";for(n=0;nl&&(t=i-l+(o=" ... ").length),n-i>l&&(n=i+l-(a=" ...").length),{str:o+e.slice(t,n).replace(/\t/g,"→")+a,pos:i-t+o.length}}function l(e,t){return n.repeat(" ",t-e.length)+e}var c=function(e,t){if(t=Object.create(t||null),!e.buffer)return null;t.maxLength||(t.maxLength=79),"number"!=typeof t.indent&&(t.indent=1),"number"!=typeof t.linesBefore&&(t.linesBefore=3),"number"!=typeof t.linesAfter&&(t.linesAfter=2);for(var i,r=/\r?\n|\r|\0/g,o=[0],c=[],s=-1;i=r.exec(e.buffer);)c.push(i.index),o.push(i.index+i[0].length),e.position<=i.index&&s<0&&(s=o.length-2);s<0&&(s=o.length-1);var u,p,f="",d=Math.min(e.line+t.linesAfter,c.length).toString().length,h=t.maxLength-(t.indent+d+3);for(u=1;u<=t.linesBefore&&!(s-u<0);u++)p=a(e.buffer,o[s-u],c[s-u],e.position-(o[s]-o[s-u]),h),f=n.repeat(" ",t.indent)+l((e.line-u+1).toString(),d)+" | "+p.str+"\n"+f;for(p=a(e.buffer,o[s],c[s],e.position,h),f+=n.repeat(" ",t.indent)+l((e.line+1).toString(),d)+" | "+p.str+"\n",f+=n.repeat("-",t.indent+d+3+p.pos)+"^\n",u=1;u<=t.linesAfter&&!(s+u>=c.length);u++)p=a(e.buffer,o[s+u],c[s+u],e.position-(o[s]-o[s+u]),h),f+=n.repeat(" ",t.indent)+l((e.line+u+1).toString(),d)+" | "+p.str+"\n";return f.replace(/\n$/,"")},s=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],u=["scalar","sequence","mapping"];var p=function(e,t){if(t=t||{},Object.keys(t).forEach((function(t){if(-1===s.indexOf(t))throw new o('Unknown option "'+t+'" is met in definition of "'+e+'" YAML type.')})),this.options=t,this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.representName=t.representName||null,this.defaultStyle=t.defaultStyle||null,this.multi=t.multi||!1,this.styleAliases=function(e){var t={};return null!==e&&Object.keys(e).forEach((function(n){e[n].forEach((function(e){t[String(e)]=n}))})),t}(t.styleAliases||null),-1===u.indexOf(this.kind))throw new o('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')};function f(e,t){var n=[];return e[t].forEach((function(e){var t=n.length;n.forEach((function(n,i){n.tag===e.tag&&n.kind===e.kind&&n.multi===e.multi&&(t=i)})),n[t]=e})),n}function d(e){return this.extend(e)}d.prototype.extend=function(e){var t=[],n=[];if(e instanceof p)n.push(e);else if(Array.isArray(e))n=n.concat(e);else{if(!e||!Array.isArray(e.implicit)&&!Array.isArray(e.explicit))throw new o("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");e.implicit&&(t=t.concat(e.implicit)),e.explicit&&(n=n.concat(e.explicit))}t.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(e.loadKind&&"scalar"!==e.loadKind)throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(e.multi)throw new o("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")})),n.forEach((function(e){if(!(e instanceof p))throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.")}));var i=Object.create(d.prototype);return i.implicit=(this.implicit||[]).concat(t),i.explicit=(this.explicit||[]).concat(n),i.compiledImplicit=f(i,"implicit"),i.compiledExplicit=f(i,"explicit"),i.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function i(e){e.multi?(n.multi[e.kind].push(e),n.multi.fallback.push(e)):n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),x=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var I=/^[-+]?[0-9]+e/;var S=new p("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!x.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n;return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,"+-".indexOf(t[0])>=0&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||n.isNegativeZero(e))},represent:function(e,t){var i;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(n.isNegativeZero(e))return"-0.0";return i=e.toString(10),I.test(i)?i.replace("e",".e"):i},defaultStyle:"lowercase"}),O=b.extend({implicit:[A,v,C,S]}),j=O,T=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),N=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");var F=new p("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:function(e){return null!==e&&(null!==T.exec(e)||null!==N.exec(e))},construct:function(e){var t,n,i,r,o,a,l,c,s=0,u=null;if(null===(t=T.exec(e))&&(t=N.exec(e)),null===t)throw new Error("Date resolve error");if(n=+t[1],i=+t[2]-1,r=+t[3],!t[4])return new Date(Date.UTC(n,i,r));if(o=+t[4],a=+t[5],l=+t[6],t[7]){for(s=t[7].slice(0,3);s.length<3;)s+="0";s=+s}return t[9]&&(u=6e4*(60*+t[10]+ +(t[11]||0)),"-"===t[9]&&(u=-u)),c=new Date(Date.UTC(n,i,r,o,a,l,s)),u&&c.setTime(c.getTime()-u),c},instanceOf:Date,represent:function(e){return e.toISOString()}});var E=new p("tag:yaml.org,2002:merge",{kind:"scalar",resolve:function(e){return"<<"===e||null===e}}),M="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";var L=new p("tag:yaml.org,2002:binary",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,i=0,r=e.length,o=M;for(n=0;n64)){if(t<0)return!1;i+=6}return i%8==0},construct:function(e){var t,n,i=e.replace(/[\r\n=]/g,""),r=i.length,o=M,a=0,l=[];for(t=0;t>16&255),l.push(a>>8&255),l.push(255&a)),a=a<<6|o.indexOf(i.charAt(t));return 0===(n=r%4*6)?(l.push(a>>16&255),l.push(a>>8&255),l.push(255&a)):18===n?(l.push(a>>10&255),l.push(a>>2&255)):12===n&&l.push(a>>4&255),new Uint8Array(l)},predicate:function(e){return"[object Uint8Array]"===Object.prototype.toString.call(e)},represent:function(e){var t,n,i="",r=0,o=e.length,a=M;for(t=0;t>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t];return 0===(n=o%3)?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}}),_=Object.prototype.hasOwnProperty,D=Object.prototype.toString;var U=new p("tag:yaml.org,2002:omap",{kind:"sequence",resolve:function(e){if(null===e)return!0;var t,n,i,r,o,a=[],l=e;for(t=0,n=l.length;t>10),56320+(e-65536&1023))}for(var ie=new Array(256),re=new Array(256),oe=0;oe<256;oe++)ie[oe]=te(oe)?1:0,re[oe]=te(oe);function ae(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||K,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function le(e,t){var n={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart};return n.snippet=c(n),new o(t,n)}function ce(e,t){throw le(e,t)}function se(e,t){e.onWarning&&e.onWarning.call(null,le(e,t))}var ue={YAML:function(e,t,n){var i,r,o;null!==e.version&&ce(e,"duplication of %YAML directive"),1!==n.length&&ce(e,"YAML directive accepts exactly one argument"),null===(i=/^([0-9]+)\.([0-9]+)$/.exec(n[0]))&&ce(e,"ill-formed argument of the YAML directive"),r=parseInt(i[1],10),o=parseInt(i[2],10),1!==r&&ce(e,"unacceptable YAML version of the document"),e.version=n[0],e.checkLineBreaks=o<2,1!==o&&2!==o&&se(e,"unsupported YAML version of the document")},TAG:function(e,t,n){var i,r;2!==n.length&&ce(e,"TAG directive accepts exactly two arguments"),i=n[0],r=n[1],G.test(i)||ce(e,"ill-formed tag handle (first argument) of the TAG directive"),P.call(e.tagMap,i)&&ce(e,'there is a previously declared suffix for "'+i+'" tag handle'),V.test(r)||ce(e,"ill-formed tag prefix (second argument) of the TAG directive");try{r=decodeURIComponent(r)}catch(t){ce(e,"tag prefix is malformed: "+r)}e.tagMap[i]=r}};function pe(e,t,n,i){var r,o,a,l;if(t1&&(e.result+=n.repeat("\n",t-1))}function be(e,t){var n,i,r=e.tag,o=e.anchor,a=[],l=!1;if(-1!==e.firstTabInLine)return!1;for(null!==e.anchor&&(e.anchorMap[e.anchor]=a),i=e.input.charCodeAt(e.position);0!==i&&(-1!==e.firstTabInLine&&(e.position=e.firstTabInLine,ce(e,"tab characters must not be used in indentation")),45===i)&&z(e.input.charCodeAt(e.position+1));)if(l=!0,e.position++,ge(e,!0,-1)&&e.lineIndent<=t)a.push(null),i=e.input.charCodeAt(e.position);else if(n=e.line,we(e,t,3,!1,!0),a.push(e.result),ge(e,!0,-1),i=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&0!==i)ce(e,"bad indentation of a sequence entry");else if(e.lineIndentt?g=1:e.lineIndent===t?g=0:e.lineIndentt?g=1:e.lineIndent===t?g=0:e.lineIndentt)&&(y&&(a=e.line,l=e.lineStart,c=e.position),we(e,t,4,!0,r)&&(y?g=e.result:m=e.result),y||(de(e,f,d,h,g,m,a,l,c),h=g=m=null),ge(e,!0,-1),s=e.input.charCodeAt(e.position)),(e.line===o||e.lineIndent>t)&&0!==s)ce(e,"bad indentation of a mapping entry");else if(e.lineIndent=0))break;0===o?ce(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):u?ce(e,"repeat of an indentation width identifier"):(p=t+o-1,u=!0)}if(Q(a)){do{a=e.input.charCodeAt(++e.position)}while(Q(a));if(35===a)do{a=e.input.charCodeAt(++e.position)}while(!J(a)&&0!==a)}for(;0!==a;){for(he(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!u||e.lineIndentp&&(p=e.lineIndent),J(a))f++;else{if(e.lineIndent0){for(r=a,o=0;r>0;r--)(a=ee(l=e.input.charCodeAt(++e.position)))>=0?o=(o<<4)+a:ce(e,"expected hexadecimal character");e.result+=ne(o),e.position++}else ce(e,"unknown escape sequence");n=i=e.position}else J(l)?(pe(e,n,i,!0),ye(e,ge(e,!1,t)),n=i=e.position):e.position===e.lineStart&&me(e)?ce(e,"unexpected end of the document within a double quoted scalar"):(e.position++,i=e.position)}ce(e,"unexpected end of the stream within a double quoted scalar")}(e,d)?y=!0:!function(e){var t,n,i;if(42!==(i=e.input.charCodeAt(e.position)))return!1;for(i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!z(i)&&!X(i);)i=e.input.charCodeAt(++e.position);return e.position===t&&ce(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),P.call(e.anchorMap,n)||ce(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],ge(e,!0,-1),!0}(e)?function(e,t,n){var i,r,o,a,l,c,s,u,p=e.kind,f=e.result;if(z(u=e.input.charCodeAt(e.position))||X(u)||35===u||38===u||42===u||33===u||124===u||62===u||39===u||34===u||37===u||64===u||96===u)return!1;if((63===u||45===u)&&(z(i=e.input.charCodeAt(e.position+1))||n&&X(i)))return!1;for(e.kind="scalar",e.result="",r=o=e.position,a=!1;0!==u;){if(58===u){if(z(i=e.input.charCodeAt(e.position+1))||n&&X(i))break}else if(35===u){if(z(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&me(e)||n&&X(u))break;if(J(u)){if(l=e.line,c=e.lineStart,s=e.lineIndent,ge(e,!1,-1),e.lineIndent>=t){a=!0,u=e.input.charCodeAt(e.position);continue}e.position=o,e.line=l,e.lineStart=c,e.lineIndent=s;break}}a&&(pe(e,r,o,!1),ye(e,e.line-l),r=o=e.position,a=!1),Q(u)||(o=e.position+1),u=e.input.charCodeAt(++e.position)}return pe(e,r,o,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,d,1===i)&&(y=!0,null===e.tag&&(e.tag="?")):(y=!0,null===e.tag&&null===e.anchor||ce(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===g&&(y=c&&be(e,h))),null===e.tag)null!==e.anchor&&(e.anchorMap[e.anchor]=e.result);else if("?"===e.tag){for(null!==e.result&&"scalar"!==e.kind&&ce(e,'unacceptable node kind for ! tag; it should be "scalar", not "'+e.kind+'"'),s=0,u=e.implicitTypes.length;s"),null!==e.result&&f.kind!==e.kind&&ce(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+f.kind+'", not "'+e.kind+'"'),f.resolve(e.result,e.tag)?(e.result=f.construct(e.result,e.tag),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):ce(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||y}function ke(e){var t,n,i,r,o=e.position,a=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);0!==(r=e.input.charCodeAt(e.position))&&(ge(e,!0,-1),r=e.input.charCodeAt(e.position),!(e.lineIndent>0||37!==r));){for(a=!0,r=e.input.charCodeAt(++e.position),t=e.position;0!==r&&!z(r);)r=e.input.charCodeAt(++e.position);for(i=[],(n=e.input.slice(t,e.position)).length<1&&ce(e,"directive name must not be less than one character in length");0!==r;){for(;Q(r);)r=e.input.charCodeAt(++e.position);if(35===r){do{r=e.input.charCodeAt(++e.position)}while(0!==r&&!J(r));break}if(J(r))break;for(t=e.position;0!==r&&!z(r);)r=e.input.charCodeAt(++e.position);i.push(e.input.slice(t,e.position))}0!==r&&he(e),P.call(ue,n)?ue[n](e,n,i):se(e,'unknown document directive "'+n+'"')}ge(e,!0,-1),0===e.lineIndent&&45===e.input.charCodeAt(e.position)&&45===e.input.charCodeAt(e.position+1)&&45===e.input.charCodeAt(e.position+2)?(e.position+=3,ge(e,!0,-1)):a&&ce(e,"directives end mark is expected"),we(e,e.lineIndent-1,4,!1,!0),ge(e,!0,-1),e.checkLineBreaks&&H.test(e.input.slice(o,e.position))&&se(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&me(e)?46===e.input.charCodeAt(e.position)&&(e.position+=3,ge(e,!0,-1)):e.position=55296&&i<=56319&&t+1=56320&&n<=57343?1024*(i-55296)+n-56320+65536:i}function Re(e){return/^\n* /.test(e)}function Be(e,t,n,i,r,o,a,l){var c,s,u=0,p=null,f=!1,d=!1,h=-1!==i,g=-1,m=De(s=Ye(e,0))&&s!==Oe&&!_e(s)&&45!==s&&63!==s&&58!==s&&44!==s&&91!==s&&93!==s&&123!==s&&125!==s&&35!==s&&38!==s&&42!==s&&33!==s&&124!==s&&61!==s&&62!==s&&39!==s&&34!==s&&37!==s&&64!==s&&96!==s&&function(e){return!_e(e)&&58!==e}(Ye(e,e.length-1));if(t||a)for(c=0;c=65536?c+=2:c++){if(!De(u=Ye(e,c)))return 5;m=m&&qe(u,p,l),p=u}else{for(c=0;c=65536?c+=2:c++){if(10===(u=Ye(e,c)))f=!0,h&&(d=d||c-g-1>i&&" "!==e[g+1],g=c);else if(!De(u))return 5;m=m&&qe(u,p,l),p=u}d=d||h&&c-g-1>i&&" "!==e[g+1]}return f||d?n>9&&Re(e)?5:a?2===o?5:2:d?4:3:!m||a||r(e)?2===o?5:2:1}function Ke(e,t,n,i,r){e.dump=function(){if(0===t.length)return 2===e.quotingType?'""':"''";if(!e.noCompatMode&&(-1!==Te.indexOf(t)||Ne.test(t)))return 2===e.quotingType?'"'+t+'"':"'"+t+"'";var a=e.indent*Math.max(1,n),l=-1===e.lineWidth?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-a),c=i||e.flowLevel>-1&&n>=e.flowLevel;switch(Be(t,c,e.indent,l,(function(t){return function(e,t){var n,i;for(n=0,i=e.implicitTypes.length;n"+Pe(t,e.indent)+We(Me(function(e,t){var n,i,r=/(\n+)([^\n]*)/g,o=(l=e.indexOf("\n"),l=-1!==l?l:e.length,r.lastIndex=l,He(e.slice(0,l),t)),a="\n"===e[0]||" "===e[0];var l;for(;i=r.exec(e);){var c=i[1],s=i[2];n=" "===s[0],o+=c+(a||n||""===s?"":"\n")+He(s,t),a=n}return o}(t,l),a));case 5:return'"'+function(e){for(var t,n="",i=0,r=0;r=65536?r+=2:r++)i=Ye(e,r),!(t=je[i])&&De(i)?(n+=e[r],i>=65536&&(n+=e[r+1])):n+=t||Fe(i);return n}(t)+'"';default:throw new o("impossible error: invalid scalar style")}}()}function Pe(e,t){var n=Re(e)?String(t):"",i="\n"===e[e.length-1];return n+(i&&("\n"===e[e.length-2]||"\n"===e)?"+":i?"":"-")+"\n"}function We(e){return"\n"===e[e.length-1]?e.slice(0,-1):e}function He(e,t){if(""===e||" "===e[0])return e;for(var n,i,r=/ [^ ]/g,o=0,a=0,l=0,c="";n=r.exec(e);)(l=n.index)-o>t&&(i=a>o?a:l,c+="\n"+e.slice(o,i),o=i+1),a=l;return c+="\n",e.length-o>t&&a>o?c+=e.slice(o,a)+"\n"+e.slice(a+1):c+=e.slice(o),c.slice(1)}function $e(e,t,n,i){var r,o,a,l="",c=e.tag;for(r=0,o=n.length;r tag resolver accepts not "'+s+'" style');i=c.represent[s](t,s)}e.dump=i}return!0}return!1}function Ve(e,t,n,i,r,a,l){e.tag=null,e.dump=n,Ge(e,n,!1)||Ge(e,n,!0);var c,s=Ie.call(e.dump),u=i;i&&(i=e.flowLevel<0||e.flowLevel>t);var p,f,d="[object Object]"===s||"[object Array]"===s;if(d&&(f=-1!==(p=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||f||2!==e.indent&&t>0)&&(r=!1),f&&e.usedDuplicates[p])e.dump="*ref_"+p;else{if(d&&f&&!e.usedDuplicates[p]&&(e.usedDuplicates[p]=!0),"[object Object]"===s)i&&0!==Object.keys(e.dump).length?(!function(e,t,n,i){var r,a,l,c,s,u,p="",f=e.tag,d=Object.keys(n);if(!0===e.sortKeys)d.sort();else if("function"==typeof e.sortKeys)d.sort(e.sortKeys);else if(e.sortKeys)throw new o("sortKeys must be a boolean or a function");for(r=0,a=d.length;r1024)&&(e.dump&&10===e.dump.charCodeAt(0)?u+="?":u+="? "),u+=e.dump,s&&(u+=Le(e,t)),Ve(e,t+1,c,!0,s)&&(e.dump&&10===e.dump.charCodeAt(0)?u+=":":u+=": ",p+=u+=e.dump));e.tag=f,e.dump=p||"{}"}(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(!function(e,t,n){var i,r,o,a,l,c="",s=e.tag,u=Object.keys(n);for(i=0,r=u.length;i1024&&(l+="? "),l+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),Ve(e,t,a,!1,!1)&&(c+=l+=e.dump));e.tag=s,e.dump="{"+c+"}"}(e,t,e.dump),f&&(e.dump="&ref_"+p+" "+e.dump));else if("[object Array]"===s)i&&0!==e.dump.length?(e.noArrayIndent&&!l&&t>0?$e(e,t-1,e.dump,r):$e(e,t,e.dump,r),f&&(e.dump="&ref_"+p+e.dump)):(!function(e,t,n){var i,r,o,a="",l=e.tag;for(i=0,r=n.length;i",e.dump=c+" "+e.dump)}return!0}function Ze(e,t){var n,i,r=[],o=[];for(Je(e,r,o),n=0,i=o.length;n=Math.abs(n.width-o)&&(o=n.width),1>=Math.abs(n.height-r)&&(r=n.height),{x:e.offsetLeft,y:e.offsetTop,width:o,height:r}}function m(e){return"html"===s(e)?e:e.assignedSlot||e.parentNode||(a(e)?e.host:null)||f(e)}function h(e){return 0<=["html","body","#document"].indexOf(s(e))?e.ownerDocument.body:i(e)&&l(e)?e:h(m(e))}function v(e,t){var o;void 0===t&&(t=[]);var r=h(e);return e=r===(null==(o=e.ownerDocument)?void 0:o.body),o=n(r),r=e?[o].concat(o.visualViewport||[],l(r)?r:[]):r,t=t.concat(r),e?t:t.concat(v(m(r)))}function g(e){return i(e)&&"fixed"!==c(e).position?e.offsetParent:null}function y(e){for(var t=n(e),o=g(e);o&&0<=["table","td","th"].indexOf(s(o))&&"static"===c(o).position;)o=g(o);if(o&&("html"===s(o)||"body"===s(o)&&"static"===c(o).position))return t;if(!o)e:{if(o=-1!==navigator.userAgent.toLowerCase().indexOf("firefox"),-1===navigator.userAgent.indexOf("Trident")||!i(e)||"fixed"!==c(e).position)for(e=m(e);i(e)&&0>["html","body"].indexOf(s(e));){var r=c(e);if("none"!==r.transform||"none"!==r.perspective||"paint"===r.contain||-1!==["transform","perspective"].indexOf(r.willChange)||o&&"filter"===r.willChange||o&&r.filter&&"none"!==r.filter){o=e;break e}e=e.parentNode}o=null}return o||t}function b(e){function t(e){o.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){o.has(e)||(e=n.get(e))&&t(e)})),r.push(e)}var n=new Map,o=new Set,r=[];return e.forEach((function(e){n.set(e.name,e)})),e.forEach((function(e){o.has(e.name)||t(e)})),r}function w(e){var t;return function(){return t||(t=new Promise((function(n){Promise.resolve().then((function(){t=void 0,n(e())}))}))),t}}function x(e){return e.split("-")[0]}function O(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&a(n))do{if(t&&e.isSameNode(t))return!0;t=t.parentNode||t.host}while(t);return!1}function j(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function E(e,r){if("viewport"===r){r=n(e);var a=f(e);r=r.visualViewport;var s=a.clientWidth;a=a.clientHeight;var l=0,u=0;r&&(s=r.width,a=r.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(l=r.offsetLeft,u=r.offsetTop)),e=j(e={width:s,height:a,x:l+p(e),y:u})}else i(r)?((e=t(r)).top+=r.clientTop,e.left+=r.clientLeft,e.bottom=e.top+r.clientHeight,e.right=e.left+r.clientWidth,e.width=r.clientWidth,e.height=r.clientHeight,e.x=e.left,e.y=e.top):(u=f(e),e=f(u),s=o(u),r=null==(a=u.ownerDocument)?void 0:a.body,a=_(e.scrollWidth,e.clientWidth,r?r.scrollWidth:0,r?r.clientWidth:0),l=_(e.scrollHeight,e.clientHeight,r?r.scrollHeight:0,r?r.clientHeight:0),u=-s.scrollLeft+p(u),s=-s.scrollTop,"rtl"===c(r||e).direction&&(u+=_(e.clientWidth,r?r.clientWidth:0)-a),e=j({width:a,height:l,x:u,y:s}));return e}function D(e,t,n){return t="clippingParents"===t?function(e){var t=v(m(e)),n=0<=["absolute","fixed"].indexOf(c(e).position)&&i(e)?y(e):e;return r(n)?t.filter((function(e){return r(e)&&O(e,n)&&"body"!==s(e)})):[]}(e):[].concat(t),(n=(n=[].concat(t,[n])).reduce((function(t,n){return n=E(e,n),t.top=_(n.top,t.top),t.right=U(n.right,t.right),t.bottom=U(n.bottom,t.bottom),t.left=_(n.left,t.left),t}),E(e,n[0]))).width=n.right-n.left,n.height=n.bottom-n.top,n.x=n.left,n.y=n.top,n}function L(e){return 0<=["top","bottom"].indexOf(e)?"x":"y"}function P(e){var t=e.reference,n=e.element,o=(e=e.placement)?x(e):null;e=e?e.split("-")[1]:null;var r=t.x+t.width/2-n.width/2,i=t.y+t.height/2-n.height/2;switch(o){case"top":r={x:r,y:t.y-n.height};break;case"bottom":r={x:r,y:t.y+t.height};break;case"right":r={x:t.x+t.width,y:i};break;case"left":r={x:t.x-n.width,y:i};break;default:r={x:t.x,y:t.y}}if(null!=(o=o?L(o):null))switch(i="y"===o?"height":"width",e){case"start":r[o]-=t[i]/2-n[i]/2;break;case"end":r[o]+=t[i]/2-n[i]/2}return r}function M(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function k(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function A(e,n){void 0===n&&(n={});var o=n;n=void 0===(n=o.placement)?e.placement:n;var i=o.boundary,a=void 0===i?"clippingParents":i,s=void 0===(i=o.rootBoundary)?"viewport":i;i=void 0===(i=o.elementContext)?"popper":i;var p=o.altBoundary,c=void 0!==p&&p;o=M("number"!=typeof(o=void 0===(o=o.padding)?0:o)?o:k(o,C));var l=e.elements.reference;p=e.rects.popper,a=D(r(c=e.elements[c?"popper"===i?"reference":"popper":i])?c:c.contextElement||f(e.elements.popper),a,s),c=P({reference:s=t(l),element:p,strategy:"absolute",placement:n}),p=j(Object.assign({},p,c)),s="popper"===i?p:s;var u={top:a.top-s.top+o.top,bottom:s.bottom-a.bottom+o.bottom,left:a.left-s.left+o.left,right:s.right-a.right+o.right};if(e=e.modifiersData.offset,"popper"===i&&e){var d=e[n];Object.keys(u).forEach((function(e){var t=0<=["right","bottom"].indexOf(e)?1:-1,n=0<=["top","bottom"].indexOf(e)?"y":"x";u[e]+=d[n]*t}))}return u}function W(){for(var e=arguments.length,t=Array(e),n=0;n(g.devicePixelRatio||1)?"translate("+e+"px, "+u+"px)":"translate3d("+e+"px, "+u+"px, 0)",m)):Object.assign({},o,((t={})[v]=a?u+"px":"",t[h]=d?e+"px":"",t.transform="",t))}function H(e){return e.replace(/left|right|bottom|top/g,(function(e){return $[e]}))}function R(e){return e.replace(/start|end/g,(function(e){return ee[e]}))}function S(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function q(e){return["top","right","bottom","left"].some((function(t){return 0<=e[t]}))}var C=["top","bottom","right","left"],N=C.reduce((function(e,t){return e.concat([t+"-start",t+"-end"])}),[]),V=[].concat(C,["auto"]).reduce((function(e,t){return e.concat([t,t+"-start",t+"-end"])}),[]),I="beforeRead read afterRead beforeMain main afterMain beforeWrite write afterWrite".split(" "),_=Math.max,U=Math.min,z=Math.round,F={placement:"bottom",modifiers:[],strategy:"absolute"},X={passive:!0},Y={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var t=e.state,o=e.instance,r=(e=e.options).scroll,i=void 0===r||r,a=void 0===(e=e.resize)||e,s=n(t.elements.popper),f=[].concat(t.scrollParents.reference,t.scrollParents.popper);return i&&f.forEach((function(e){e.addEventListener("scroll",o.update,X)})),a&&s.addEventListener("resize",o.update,X),function(){i&&f.forEach((function(e){e.removeEventListener("scroll",o.update,X)})),a&&s.removeEventListener("resize",o.update,X)}},data:{}},G={name:"popperOffsets",enabled:!0,phase:"read",fn:function(e){var t=e.state;t.modifiersData[e.name]=P({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})},data:{}},J={top:"auto",right:"auto",bottom:"auto",left:"auto"},K={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,n=e.options;e=void 0===(e=n.gpuAcceleration)||e;var o=n.adaptive;o=void 0===o||o,n=void 0===(n=n.roundOffsets)||n,e={placement:x(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:e},null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,T(Object.assign({},e,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:o,roundOffsets:n})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,T(Object.assign({},e,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:n})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}},Q={name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var n=t.styles[e]||{},o=t.attributes[e]||{},r=t.elements[e];i(r)&&s(r)&&(Object.assign(r.style,n),Object.keys(o).forEach((function(e){var t=o[e];!1===t?r.removeAttribute(e):r.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach((function(e){var o=t.elements[e],r=t.attributes[e]||{};e=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:n[e]).reduce((function(e,t){return e[t]="",e}),{}),i(o)&&s(o)&&(Object.assign(o.style,e),Object.keys(r).forEach((function(e){o.removeAttribute(e)})))}))}},requires:["computeStyles"]},Z={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,n=e.name,o=void 0===(e=e.options.offset)?[0,0]:e,r=(e=V.reduce((function(e,n){var r=t.rects,i=x(n),a=0<=["left","top"].indexOf(i)?-1:1,s="function"==typeof o?o(Object.assign({},r,{placement:n})):o;return r=(r=s[0])||0,s=((s=s[1])||0)*a,i=0<=["left","right"].indexOf(i)?{x:s,y:r}:{x:r,y:s},e[n]=i,e}),{}))[t.placement],i=r.x;r=r.y,null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=i,t.modifiersData.popperOffsets.y+=r),t.modifiersData[n]=e}},$={left:"right",right:"left",bottom:"top",top:"bottom"},ee={start:"end",end:"start"},te={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options;if(e=e.name,!t.modifiersData[e]._skip){var o=n.mainAxis;o=void 0===o||o;var r=n.altAxis;r=void 0===r||r;var i=n.fallbackPlacements,a=n.padding,s=n.boundary,f=n.rootBoundary,p=n.altBoundary,c=n.flipVariations,l=void 0===c||c,u=n.allowedAutoPlacements;c=x(n=t.options.placement),i=i||(c!==n&&l?function(e){if("auto"===x(e))return[];var t=H(e);return[R(e),t,R(t)]}(n):[H(n)]);var d=[n].concat(i).reduce((function(e,n){return e.concat("auto"===x(n)?function(e,t){void 0===t&&(t={});var n=t.boundary,o=t.rootBoundary,r=t.padding,i=t.flipVariations,a=t.allowedAutoPlacements,s=void 0===a?V:a,f=t.placement.split("-")[1];0===(i=(t=f?i?N:N.filter((function(e){return e.split("-")[1]===f})):C).filter((function(e){return 0<=s.indexOf(e)}))).length&&(i=t);var p=i.reduce((function(t,i){return t[i]=A(e,{placement:i,boundary:n,rootBoundary:o,padding:r})[x(i)],t}),{});return Object.keys(p).sort((function(e,t){return p[e]-p[t]}))}(t,{placement:n,boundary:s,rootBoundary:f,padding:a,flipVariations:l,allowedAutoPlacements:u}):n)}),[]);n=t.rects.reference,i=t.rects.popper;var m=new Map;c=!0;for(var h=d[0],v=0;vi[O]&&(b=H(b)),O=H(b),w=[],o&&w.push(0>=j[y]),r&&w.push(0>=j[b],0>=j[O]),w.every((function(e){return e}))){h=g,c=!1;break}m.set(g,w)}if(c)for(o=function(e){var t=d.find((function(t){if(t=m.get(t))return t.slice(0,e).every((function(e){return e}))}));if(t)return h=t,"break"},r=l?3:1;0label { 478 | font-size: 12px; 479 | font-weight: 700; 480 | display: -webkit-box; 481 | display: -ms-flexbox; 482 | display: flex; 483 | -webkit-box-orient: vertical; 484 | -webkit-box-direction: normal; 485 | -ms-flex-direction: column; 486 | flex-direction: column; 487 | margin: -20px 15px 0 0; 488 | font-family: Titillium Web, sans-serif; 489 | color: #3b4151 490 | } 491 | 492 | .swagger-ui .scheme-container .schemes>label select { 493 | min-width: 130px; 494 | text-transform: uppercase 495 | } 496 | 497 | .swagger-ui .loading-container { 498 | padding: 40px 0 60px 499 | } 500 | 501 | .swagger-ui .loading-container .loading { 502 | position: relative 503 | } 504 | 505 | .swagger-ui .loading-container .loading:after { 506 | font-size: 10px; 507 | font-weight: 700; 508 | position: absolute; 509 | top: 50%; 510 | left: 50%; 511 | content: "loading"; 512 | -webkit-transform: translate(-50%, -50%); 513 | transform: translate(-50%, -50%); 514 | text-transform: uppercase; 515 | font-family: Titillium Web, sans-serif; 516 | color: #3b4151 517 | } 518 | 519 | .swagger-ui .loading-container .loading:before { 520 | position: absolute; 521 | top: 50%; 522 | left: 50%; 523 | display: block; 524 | width: 60px; 525 | height: 60px; 526 | margin: -30px; 527 | content: ""; 528 | -webkit-animation: rotation 1s infinite linear, opacity .5s; 529 | animation: rotation 1s infinite linear, opacity .5s; 530 | opacity: 1; 531 | border: 2px solid rgba(85, 85, 85, .1); 532 | border-top-color: rgba(0, 0, 0, .6); 533 | border-radius: 100%; 534 | -webkit-backface-visibility: hidden; 535 | backface-visibility: hidden 536 | } 537 | 538 | @-webkit-keyframes rotation { 539 | to { 540 | -webkit-transform: rotate(1turn); 541 | transform: rotate(1turn) 542 | } 543 | } 544 | 545 | @keyframes rotation { 546 | to { 547 | -webkit-transform: rotate(1turn); 548 | transform: rotate(1turn) 549 | } 550 | } 551 | 552 | @-webkit-keyframes blinker { 553 | 50% { 554 | opacity: 0 555 | } 556 | } 557 | 558 | @keyframes blinker { 559 | 50% { 560 | opacity: 0 561 | } 562 | } 563 | 564 | .swagger-ui .btn { 565 | font-size: 14px; 566 | font-weight: 700; 567 | padding: 5px 23px; 568 | -webkit-transition: all .3s; 569 | transition: all .3s; 570 | border: 2px solid #888; 571 | border-radius: 4px; 572 | background: transparent; 573 | box-shadow: 0 1px 2px rgba(0, 0, 0, .1); 574 | font-family: Titillium Web, sans-serif; 575 | color: #3b4151 576 | } 577 | 578 | .swagger-ui .btn[disabled] { 579 | cursor: not-allowed; 580 | opacity: .3 581 | } 582 | 583 | .swagger-ui .btn:hover { 584 | box-shadow: 0 0 5px rgba(0, 0, 0, .3) 585 | } 586 | 587 | .swagger-ui .btn.cancel { 588 | border-color: #ff6060; 589 | font-family: Titillium Web, sans-serif; 590 | color: #ff6060 591 | } 592 | 593 | .swagger-ui .btn.authorize { 594 | line-height: 1; 595 | display: inline; 596 | color: #49cc90; 597 | border-color: #49cc90 598 | } 599 | 600 | .swagger-ui .btn.authorize span { 601 | float: left; 602 | padding: 4px 20px 0 0 603 | } 604 | 605 | .swagger-ui .btn.authorize svg { 606 | fill: #49cc90 607 | } 608 | 609 | .swagger-ui .btn.execute { 610 | -webkit-animation: pulse 2s infinite; 611 | animation: pulse 2s infinite; 612 | color: #fff; 613 | border-color: #4990e2 614 | } 615 | 616 | @-webkit-keyframes pulse { 617 | 0% { 618 | color: #fff; 619 | background: #4990e2; 620 | box-shadow: 0 0 0 0 rgba(73, 144, 226, .8) 621 | } 622 | 70% { 623 | box-shadow: 0 0 0 5px rgba(73, 144, 226, 0) 624 | } 625 | to { 626 | color: #fff; 627 | background: #4990e2; 628 | box-shadow: 0 0 0 0 rgba(73, 144, 226, 0) 629 | } 630 | } 631 | 632 | @keyframes pulse { 633 | 0% { 634 | color: #fff; 635 | background: #4990e2; 636 | box-shadow: 0 0 0 0 rgba(73, 144, 226, .8) 637 | } 638 | 70% { 639 | box-shadow: 0 0 0 5px rgba(73, 144, 226, 0) 640 | } 641 | to { 642 | color: #fff; 643 | background: #4990e2; 644 | box-shadow: 0 0 0 0 rgba(73, 144, 226, 0) 645 | } 646 | } 647 | 648 | .swagger-ui .btn-group { 649 | display: -webkit-box; 650 | display: -ms-flexbox; 651 | display: flex; 652 | padding: 30px 653 | } 654 | 655 | .swagger-ui .btn-group .btn { 656 | -webkit-box-flex: 1; 657 | -ms-flex: 1; 658 | flex: 1 659 | } 660 | 661 | .swagger-ui .btn-group .btn:first-child { 662 | border-radius: 4px 0 0 4px 663 | } 664 | 665 | .swagger-ui .btn-group .btn:last-child { 666 | border-radius: 0 4px 4px 0 667 | } 668 | 669 | .swagger-ui .authorization__btn { 670 | padding: 0 10px; 671 | border: none; 672 | background: none 673 | } 674 | 675 | .swagger-ui .authorization__btn.locked { 676 | opacity: 1 677 | } 678 | 679 | .swagger-ui .authorization__btn.unlocked { 680 | opacity: .4 681 | } 682 | 683 | .swagger-ui .expand-methods, .swagger-ui .expand-operation { 684 | border: none; 685 | background: none 686 | } 687 | 688 | .swagger-ui .expand-methods svg, .swagger-ui .expand-operation svg { 689 | width: 20px; 690 | height: 20px 691 | } 692 | 693 | .swagger-ui .expand-methods { 694 | padding: 0 10px 695 | } 696 | 697 | .swagger-ui .expand-methods:hover svg { 698 | fill: #444 699 | } 700 | 701 | .swagger-ui .expand-methods svg { 702 | -webkit-transition: all .3s; 703 | transition: all .3s; 704 | fill: #777 705 | } 706 | 707 | .swagger-ui button { 708 | cursor: pointer; 709 | outline: none 710 | } 711 | 712 | .swagger-ui select { 713 | font-size: 14px; 714 | font-weight: 700; 715 | padding: 5px 40px 5px 10px; 716 | border: 2px solid #41444e; 717 | border-radius: 4px; 718 | background: #f7f7f7 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat; 719 | background-size: 20px; 720 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .25); 721 | font-family: Titillium Web, sans-serif; 722 | color: #3b4151; 723 | -webkit-appearance: none; 724 | -moz-appearance: none; 725 | appearance: none 726 | } 727 | 728 | .swagger-ui select[multiple] { 729 | margin: 5px 0; 730 | padding: 5px; 731 | background: #f7f7f7 732 | } 733 | 734 | .swagger-ui .opblock-body select { 735 | min-width: 230px 736 | } 737 | 738 | .swagger-ui label { 739 | font-size: 12px; 740 | font-weight: 700; 741 | margin: 0 0 5px; 742 | font-family: Titillium Web, sans-serif; 743 | color: #3b4151 744 | } 745 | 746 | .swagger-ui input[type=email], .swagger-ui input[type=password], .swagger-ui input[type=search], .swagger-ui input[type=text] { 747 | min-width: 100px; 748 | margin: 5px 0; 749 | padding: 8px 10px; 750 | border: 1px solid #d9d9d9; 751 | border-radius: 4px; 752 | background: #fff 753 | } 754 | 755 | .swagger-ui input[type=email].invalid, .swagger-ui input[type=password].invalid, .swagger-ui input[type=search].invalid, .swagger-ui input[type=text].invalid { 756 | -webkit-animation: shake .4s 1; 757 | animation: shake .4s 1; 758 | border-color: #f93e3e; 759 | background: #feebeb 760 | } 761 | 762 | @-webkit-keyframes shake { 763 | 10%, 90% { 764 | -webkit-transform: translate3d(-1px, 0, 0); 765 | transform: translate3d(-1px, 0, 0) 766 | } 767 | 20%, 80% { 768 | -webkit-transform: translate3d(2px, 0, 0); 769 | transform: translate3d(2px, 0, 0) 770 | } 771 | 30%, 50%, 70% { 772 | -webkit-transform: translate3d(-4px, 0, 0); 773 | transform: translate3d(-4px, 0, 0) 774 | } 775 | 40%, 60% { 776 | -webkit-transform: translate3d(4px, 0, 0); 777 | transform: translate3d(4px, 0, 0) 778 | } 779 | } 780 | 781 | @keyframes shake { 782 | 10%, 90% { 783 | -webkit-transform: translate3d(-1px, 0, 0); 784 | transform: translate3d(-1px, 0, 0) 785 | } 786 | 20%, 80% { 787 | -webkit-transform: translate3d(2px, 0, 0); 788 | transform: translate3d(2px, 0, 0) 789 | } 790 | 30%, 50%, 70% { 791 | -webkit-transform: translate3d(-4px, 0, 0); 792 | transform: translate3d(-4px, 0, 0) 793 | } 794 | 40%, 60% { 795 | -webkit-transform: translate3d(4px, 0, 0); 796 | transform: translate3d(4px, 0, 0) 797 | } 798 | } 799 | 800 | .swagger-ui textarea { 801 | font-size: 12px; 802 | width: 100%; 803 | min-height: 280px; 804 | padding: 10px; 805 | border: none; 806 | border-radius: 4px; 807 | outline: none; 808 | background: hsla(0, 0%, 100%, .8); 809 | font-family: Source Code Pro, monospace; 810 | font-weight: 600; 811 | color: #3b4151 812 | } 813 | 814 | .swagger-ui textarea:focus { 815 | border: 2px solid #61affe 816 | } 817 | 818 | .swagger-ui textarea.curl { 819 | font-size: 12px; 820 | min-height: 100px; 821 | margin: 0; 822 | padding: 10px; 823 | resize: none; 824 | border-radius: 4px; 825 | background: #41444e; 826 | font-family: Source Code Pro, monospace; 827 | font-weight: 600; 828 | color: #fff 829 | } 830 | 831 | .swagger-ui .checkbox { 832 | padding: 5px 0 10px; 833 | -webkit-transition: opacity .5s; 834 | transition: opacity .5s; 835 | color: #333 836 | } 837 | 838 | .swagger-ui .checkbox label { 839 | display: -webkit-box; 840 | display: -ms-flexbox; 841 | display: flex 842 | } 843 | 844 | .swagger-ui .checkbox p { 845 | font-weight: 400!important; 846 | font-style: italic; 847 | margin: 0!important; 848 | font-family: Source Code Pro, monospace; 849 | font-weight: 600; 850 | color: #3b4151 851 | } 852 | 853 | .swagger-ui .checkbox input[type=checkbox] { 854 | display: none 855 | } 856 | 857 | .swagger-ui .checkbox input[type=checkbox]+label>.item { 858 | position: relative; 859 | top: 3px; 860 | display: inline-block; 861 | width: 16px; 862 | height: 16px; 863 | margin: 0 8px 0 0; 864 | padding: 5px; 865 | cursor: pointer; 866 | border-radius: 1px; 867 | background: #e8e8e8; 868 | box-shadow: 0 0 0 2px #e8e8e8; 869 | -webkit-box-flex: 0; 870 | -ms-flex: none; 871 | flex: none 872 | } 873 | 874 | .swagger-ui .checkbox input[type=checkbox]+label>.item:active { 875 | -webkit-transform: scale(.9); 876 | transform: scale(.9) 877 | } 878 | 879 | .swagger-ui .checkbox input[type=checkbox]:checked+label>.item { 880 | background: #e8e8e8 url("data:image/svg+xml;charset=utf-8,%3Csvg width='10' height='8' viewBox='3 7 10 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2341474E' fill-rule='evenodd' d='M6.333 15L3 11.667l1.333-1.334 2 2L11.667 7 13 8.333z'/%3E%3C/svg%3E") 50% no-repeat 881 | } 882 | 883 | .swagger-ui .dialog-ux { 884 | position: fixed; 885 | z-index: 9999; 886 | top: 0; 887 | right: 0; 888 | bottom: 0; 889 | left: 0 890 | } 891 | 892 | .swagger-ui .dialog-ux .backdrop-ux { 893 | position: fixed; 894 | top: 0; 895 | right: 0; 896 | bottom: 0; 897 | left: 0; 898 | background: rgba(0, 0, 0, .8) 899 | } 900 | 901 | .swagger-ui .dialog-ux .modal-ux { 902 | position: absolute; 903 | z-index: 9999; 904 | top: 50%; 905 | left: 50%; 906 | width: 100%; 907 | min-width: 300px; 908 | max-width: 650px; 909 | -webkit-transform: translate(-50%, -50%); 910 | transform: translate(-50%, -50%); 911 | border: 1px solid #ebebeb; 912 | border-radius: 4px; 913 | background: #fff; 914 | box-shadow: 0 10px 30px 0 rgba(0, 0, 0, .2) 915 | } 916 | 917 | .swagger-ui .dialog-ux .modal-ux-content { 918 | overflow-y: auto; 919 | max-height: 540px; 920 | padding: 20px 921 | } 922 | 923 | .swagger-ui .dialog-ux .modal-ux-content p { 924 | font-size: 12px; 925 | margin: 0 0 5px; 926 | color: #41444e; 927 | font-family: Open Sans, sans-serif; 928 | color: #3b4151 929 | } 930 | 931 | .swagger-ui .dialog-ux .modal-ux-content h4 { 932 | font-size: 18px; 933 | font-weight: 600; 934 | margin: 15px 0 0; 935 | font-family: Titillium Web, sans-serif; 936 | color: #3b4151 937 | } 938 | 939 | .swagger-ui .dialog-ux .modal-ux-header { 940 | display: -webkit-box; 941 | display: -ms-flexbox; 942 | display: flex; 943 | padding: 12px 0; 944 | border-bottom: 1px solid #ebebeb; 945 | -webkit-box-align: center; 946 | -ms-flex-align: center; 947 | align-items: center 948 | } 949 | 950 | .swagger-ui .dialog-ux .modal-ux-header .close-modal { 951 | padding: 0 10px; 952 | border: none; 953 | background: none; 954 | -webkit-appearance: none; 955 | -moz-appearance: none; 956 | appearance: none 957 | } 958 | 959 | .swagger-ui .dialog-ux .modal-ux-header h3 { 960 | font-size: 20px; 961 | font-weight: 600; 962 | margin: 0; 963 | padding: 0 20px; 964 | -webkit-box-flex: 1; 965 | -ms-flex: 1; 966 | flex: 1; 967 | font-family: Titillium Web, sans-serif; 968 | color: #3b4151 969 | } 970 | 971 | .swagger-ui .model { 972 | font-size: 12px; 973 | font-weight: 300; 974 | font-family: Source Code Pro, monospace; 975 | font-weight: 600; 976 | color: #3b4151 977 | } 978 | 979 | .swagger-ui .model-toggle { 980 | font-size: 10px; 981 | position: relative; 982 | top: 6px; 983 | display: inline-block; 984 | margin: auto .3em; 985 | cursor: pointer; 986 | -webkit-transition: -webkit-transform .15s ease-in; 987 | transition: -webkit-transform .15s ease-in; 988 | transition: transform .15s ease-in; 989 | transition: transform .15s ease-in, -webkit-transform .15s ease-in; 990 | -webkit-transform: rotate(90deg); 991 | transform: rotate(90deg); 992 | -webkit-transform-origin: 50% 50%; 993 | transform-origin: 50% 50% 994 | } 995 | 996 | .swagger-ui .model-toggle.collapsed { 997 | -webkit-transform: rotate(0deg); 998 | transform: rotate(0deg) 999 | } 1000 | 1001 | .swagger-ui .model-toggle:after { 1002 | display: block; 1003 | width: 20px; 1004 | height: 20px; 1005 | content: ""; 1006 | background: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'/%3E%3C/svg%3E") 50% no-repeat; 1007 | background-size: 100% 1008 | } 1009 | 1010 | .swagger-ui .model-jump-to-path { 1011 | position: relative; 1012 | cursor: pointer 1013 | } 1014 | 1015 | .swagger-ui .model-jump-to-path .view-line-link { 1016 | position: absolute; 1017 | top: -.4em; 1018 | cursor: pointer 1019 | } 1020 | 1021 | .swagger-ui .model-title { 1022 | position: relative 1023 | } 1024 | 1025 | .swagger-ui .model-title:hover .model-hint { 1026 | visibility: visible 1027 | } 1028 | 1029 | .swagger-ui .model-hint { 1030 | position: absolute; 1031 | top: -1.8em; 1032 | visibility: hidden; 1033 | padding: .1em .5em; 1034 | white-space: nowrap; 1035 | color: #ebebeb; 1036 | border-radius: 4px; 1037 | background: rgba(0, 0, 0, .7) 1038 | } 1039 | 1040 | .swagger-ui section.models { 1041 | margin: 30px 0; 1042 | border: 1px solid rgba(59, 65, 81, .3); 1043 | border-radius: 4px 1044 | } 1045 | 1046 | .swagger-ui section.models.is-open { 1047 | padding: 0 0 20px 1048 | } 1049 | 1050 | .swagger-ui section.models.is-open h4 { 1051 | margin: 0 0 5px; 1052 | border-bottom: 1px solid rgba(59, 65, 81, .3) 1053 | } 1054 | 1055 | .swagger-ui section.models.is-open h4 svg { 1056 | -webkit-transform: rotate(90deg); 1057 | transform: rotate(90deg) 1058 | } 1059 | 1060 | .swagger-ui section.models h4 { 1061 | font-size: 16px; 1062 | display: -webkit-box; 1063 | display: -ms-flexbox; 1064 | display: flex; 1065 | margin: 0; 1066 | padding: 10px 20px 10px 10px; 1067 | cursor: pointer; 1068 | -webkit-transition: all .2s; 1069 | transition: all .2s; 1070 | font-family: Titillium Web, sans-serif; 1071 | color: #777; 1072 | -webkit-box-align: center; 1073 | -ms-flex-align: center; 1074 | align-items: center 1075 | } 1076 | 1077 | .swagger-ui section.models h4 svg { 1078 | -webkit-transition: all .4s; 1079 | transition: all .4s 1080 | } 1081 | 1082 | .swagger-ui section.models h4 span { 1083 | -webkit-box-flex: 1; 1084 | -ms-flex: 1; 1085 | flex: 1 1086 | } 1087 | 1088 | .swagger-ui section.models h4:hover { 1089 | background: rgba(0, 0, 0, .02) 1090 | } 1091 | 1092 | .swagger-ui section.models h5 { 1093 | font-size: 16px; 1094 | margin: 0 0 10px; 1095 | font-family: Titillium Web, sans-serif; 1096 | color: #777 1097 | } 1098 | 1099 | .swagger-ui section.models .model-jump-to-path { 1100 | position: relative; 1101 | top: 5px 1102 | } 1103 | 1104 | .swagger-ui section.models .model-container { 1105 | margin: 0 20px 15px; 1106 | -webkit-transition: all .5s; 1107 | transition: all .5s; 1108 | border-radius: 4px; 1109 | background: rgba(0, 0, 0, .05) 1110 | } 1111 | 1112 | .swagger-ui section.models .model-container:hover { 1113 | background: rgba(0, 0, 0, .07) 1114 | } 1115 | 1116 | .swagger-ui section.models .model-container:first-of-type { 1117 | margin: 20px 1118 | } 1119 | 1120 | .swagger-ui section.models .model-container:last-of-type { 1121 | margin: 0 20px 1122 | } 1123 | 1124 | .swagger-ui section.models .model-box { 1125 | background: none 1126 | } 1127 | 1128 | .swagger-ui .model-box { 1129 | padding: 10px; 1130 | border-radius: 4px; 1131 | background: rgba(0, 0, 0, .1) 1132 | } 1133 | 1134 | .swagger-ui .model-box .model-jump-to-path { 1135 | position: relative; 1136 | top: 4px 1137 | } 1138 | 1139 | .swagger-ui .model-title { 1140 | font-size: 16px; 1141 | font-family: Titillium Web, sans-serif; 1142 | color: #555 1143 | } 1144 | 1145 | .swagger-ui span>span.model, .swagger-ui span>span.model .brace-close { 1146 | padding: 0 0 0 10px 1147 | } 1148 | 1149 | .swagger-ui .prop-type { 1150 | color: #55a 1151 | } 1152 | 1153 | .swagger-ui .prop-enum { 1154 | display: block 1155 | } 1156 | 1157 | .swagger-ui .prop-format { 1158 | color: #999 1159 | } 1160 | 1161 | .swagger-ui table { 1162 | width: 100%; 1163 | padding: 0 10px; 1164 | border-collapse: collapse 1165 | } 1166 | 1167 | .swagger-ui table.model tbody tr td { 1168 | padding: 0; 1169 | vertical-align: top 1170 | } 1171 | 1172 | .swagger-ui table.model tbody tr td:first-of-type { 1173 | width: 100px; 1174 | padding: 0 1175 | } 1176 | 1177 | .swagger-ui table.headers td { 1178 | font-size: 12px; 1179 | font-weight: 300; 1180 | vertical-align: middle; 1181 | font-family: Source Code Pro, monospace; 1182 | font-weight: 600; 1183 | color: #3b4151 1184 | } 1185 | 1186 | .swagger-ui table tbody tr td { 1187 | padding: 10px 0 0; 1188 | vertical-align: top 1189 | } 1190 | 1191 | .swagger-ui table tbody tr td:first-of-type { 1192 | width: 20%; 1193 | padding: 10px 0 1194 | } 1195 | 1196 | .swagger-ui table thead tr td, .swagger-ui table thead tr th { 1197 | font-size: 12px; 1198 | font-weight: 700; 1199 | padding: 12px 0; 1200 | text-align: left; 1201 | border-bottom: 1px solid rgba(59, 65, 81, .2); 1202 | font-family: Open Sans, sans-serif; 1203 | color: #3b4151 1204 | } 1205 | 1206 | .swagger-ui .parameters-col_description p { 1207 | font-size: 14px; 1208 | margin: 0; 1209 | font-family: Open Sans, sans-serif; 1210 | color: #3b4151 1211 | } 1212 | 1213 | .swagger-ui .parameters-col_description input[type=text] { 1214 | width: 100%; 1215 | max-width: 340px 1216 | } 1217 | 1218 | .swagger-ui .parameter__name { 1219 | font-size: 16px; 1220 | font-weight: 400; 1221 | font-family: Titillium Web, sans-serif; 1222 | color: #3b4151 1223 | } 1224 | 1225 | .swagger-ui .parameter__name.required { 1226 | font-weight: 700 1227 | } 1228 | 1229 | .swagger-ui .parameter__name.required:after { 1230 | font-size: 10px; 1231 | position: relative; 1232 | top: -6px; 1233 | padding: 5px; 1234 | content: "required"; 1235 | color: rgba(255, 0, 0, .6) 1236 | } 1237 | 1238 | .swagger-ui .parameter__in { 1239 | font-size: 12px; 1240 | font-style: italic; 1241 | font-family: Source Code Pro, monospace; 1242 | font-weight: 600; 1243 | color: #888 1244 | } 1245 | 1246 | .swagger-ui .table-container { 1247 | padding: 20px 1248 | } 1249 | 1250 | .swagger-ui .topbar { 1251 | padding: 8px 30px; 1252 | background-color: #89bf04 1253 | } 1254 | 1255 | .swagger-ui .topbar .topbar-wrapper { 1256 | -ms-flex-align: center 1257 | } 1258 | 1259 | .swagger-ui .topbar .topbar-wrapper, .swagger-ui .topbar a { 1260 | display: -webkit-box; 1261 | display: -ms-flexbox; 1262 | display: flex; 1263 | -webkit-box-align: center; 1264 | align-items: center 1265 | } 1266 | 1267 | .swagger-ui .topbar a { 1268 | font-size: 1.5em; 1269 | font-weight: 700; 1270 | text-decoration: none; 1271 | -webkit-box-flex: 1; 1272 | -ms-flex: 1; 1273 | flex: 1; 1274 | -ms-flex-align: center; 1275 | font-family: Titillium Web, sans-serif; 1276 | color: #fff 1277 | } 1278 | 1279 | .swagger-ui .topbar a span { 1280 | margin: 0; 1281 | padding: 0 10px 1282 | } 1283 | 1284 | .swagger-ui .topbar .download-url-wrapper { 1285 | display: -webkit-box; 1286 | display: -ms-flexbox; 1287 | display: flex 1288 | } 1289 | 1290 | .swagger-ui .topbar .download-url-wrapper input[type=text] { 1291 | min-width: 350px; 1292 | margin: 0; 1293 | border: 2px solid #547f00; 1294 | border-radius: 4px 0 0 4px; 1295 | outline: none 1296 | } 1297 | 1298 | .swagger-ui .topbar .download-url-wrapper .download-url-button { 1299 | font-size: 16px; 1300 | font-weight: 700; 1301 | padding: 4px 40px; 1302 | border: none; 1303 | border-radius: 0 4px 4px 0; 1304 | background: #547f00; 1305 | font-family: Titillium Web, sans-serif; 1306 | color: #fff 1307 | } 1308 | 1309 | .swagger-ui .info { 1310 | margin: 50px 0 1311 | } 1312 | 1313 | .swagger-ui .info hgroup.main { 1314 | margin: 0 0 20px 1315 | } 1316 | 1317 | .swagger-ui .info hgroup.main a { 1318 | font-size: 12px 1319 | } 1320 | 1321 | .swagger-ui .info p { 1322 | font-size: 14px; 1323 | font-family: Open Sans, sans-serif; 1324 | color: #3b4151 1325 | } 1326 | 1327 | .swagger-ui .info code { 1328 | padding: 3px 5px; 1329 | border-radius: 4px; 1330 | background: rgba(0, 0, 0, .05); 1331 | font-family: Source Code Pro, monospace; 1332 | font-weight: 600; 1333 | color: #9012fe 1334 | } 1335 | 1336 | .swagger-ui .info a { 1337 | font-size: 14px; 1338 | -webkit-transition: all .4s; 1339 | transition: all .4s; 1340 | font-family: Open Sans, sans-serif; 1341 | color: #4990e2 1342 | } 1343 | 1344 | .swagger-ui .info a:hover { 1345 | color: #1f69c0 1346 | } 1347 | 1348 | .swagger-ui .info>div { 1349 | margin: 0 0 5px 1350 | } 1351 | 1352 | .swagger-ui .info .base-url { 1353 | font-size: 12px; 1354 | font-weight: 300!important; 1355 | margin: 0; 1356 | font-family: Source Code Pro, monospace; 1357 | font-weight: 600; 1358 | color: #3b4151 1359 | } 1360 | 1361 | .swagger-ui .info .title { 1362 | font-size: 36px; 1363 | margin: 0; 1364 | font-family: Open Sans, sans-serif; 1365 | color: #3b4151 1366 | } 1367 | 1368 | .swagger-ui .info .title small { 1369 | font-size: 10px; 1370 | position: relative; 1371 | top: -5px; 1372 | display: inline-block; 1373 | margin: 0 0 0 5px; 1374 | padding: 2px 4px; 1375 | vertical-align: super; 1376 | border-radius: 57px; 1377 | background: #7d8492 1378 | } 1379 | 1380 | .swagger-ui .info .title small pre { 1381 | margin: 0; 1382 | font-family: Titillium Web, sans-serif; 1383 | color: #fff 1384 | } 1385 | 1386 | .swagger-ui .auth-btn-wrapper { 1387 | display: -webkit-box; 1388 | display: -ms-flexbox; 1389 | display: flex; 1390 | padding: 10px 0; 1391 | -webkit-box-pack: center; 1392 | -ms-flex-pack: center; 1393 | justify-content: center 1394 | } 1395 | 1396 | .swagger-ui .auth-wrapper { 1397 | display: -webkit-box; 1398 | display: -ms-flexbox; 1399 | display: flex; 1400 | -webkit-box-flex: 1; 1401 | -ms-flex: 1; 1402 | flex: 1; 1403 | -webkit-box-pack: end; 1404 | -ms-flex-pack: end; 1405 | justify-content: flex-end 1406 | } 1407 | 1408 | .swagger-ui .auth-wrapper .authorize { 1409 | padding-right: 20px 1410 | } 1411 | 1412 | .swagger-ui .auth-container { 1413 | margin: 0 0 10px; 1414 | padding: 10px 20px; 1415 | border-bottom: 1px solid #ebebeb 1416 | } 1417 | 1418 | .swagger-ui .auth-container:last-of-type { 1419 | margin: 0; 1420 | padding: 10px 20px; 1421 | border: 0 1422 | } 1423 | 1424 | .swagger-ui .auth-container h4 { 1425 | margin: 5px 0 15px!important 1426 | } 1427 | 1428 | .swagger-ui .auth-container .wrapper { 1429 | margin: 0; 1430 | padding: 0 1431 | } 1432 | 1433 | .swagger-ui .auth-container input[type=password], .swagger-ui .auth-container input[type=text] { 1434 | min-width: 230px 1435 | } 1436 | 1437 | .swagger-ui .auth-container .errors { 1438 | font-size: 12px; 1439 | padding: 10px; 1440 | border-radius: 4px; 1441 | font-family: Source Code Pro, monospace; 1442 | font-weight: 600; 1443 | color: #3b4151 1444 | } 1445 | 1446 | .swagger-ui .scopes h2 { 1447 | font-size: 14px; 1448 | font-family: Titillium Web, sans-serif; 1449 | color: #3b4151 1450 | } 1451 | 1452 | .swagger-ui .scope-def { 1453 | padding: 0 0 20px 1454 | } 1455 | 1456 | .swagger-ui .errors-wrapper { 1457 | margin: 20px; 1458 | padding: 10px 20px; 1459 | -webkit-animation: scaleUp .5s; 1460 | animation: scaleUp .5s; 1461 | border: 2px solid #f93e3e; 1462 | border-radius: 4px; 1463 | background: rgba(249, 62, 62, .1) 1464 | } 1465 | 1466 | .swagger-ui .errors-wrapper .error-wrapper { 1467 | margin: 0 0 10px 1468 | } 1469 | 1470 | .swagger-ui .errors-wrapper .errors h4 { 1471 | font-size: 14px; 1472 | margin: 0; 1473 | font-family: Source Code Pro, monospace; 1474 | font-weight: 600; 1475 | color: #3b4151 1476 | } 1477 | 1478 | .swagger-ui .errors-wrapper hgroup { 1479 | display: -webkit-box; 1480 | display: -ms-flexbox; 1481 | display: flex; 1482 | -webkit-box-align: center; 1483 | -ms-flex-align: center; 1484 | align-items: center 1485 | } 1486 | 1487 | .swagger-ui .errors-wrapper hgroup h4 { 1488 | font-size: 20px; 1489 | margin: 0; 1490 | -webkit-box-flex: 1; 1491 | -ms-flex: 1; 1492 | flex: 1; 1493 | font-family: Titillium Web, sans-serif; 1494 | color: #3b4151 1495 | } 1496 | 1497 | @-webkit-keyframes scaleUp { 1498 | 0% { 1499 | -webkit-transform: scale(.8); 1500 | transform: scale(.8); 1501 | opacity: 0 1502 | } 1503 | to { 1504 | -webkit-transform: scale(1); 1505 | transform: scale(1); 1506 | opacity: 1 1507 | } 1508 | } 1509 | 1510 | @keyframes scaleUp { 1511 | 0% { 1512 | -webkit-transform: scale(.8); 1513 | transform: scale(.8); 1514 | opacity: 0 1515 | } 1516 | to { 1517 | -webkit-transform: scale(1); 1518 | transform: scale(1); 1519 | opacity: 1 1520 | } 1521 | } 1522 | 1523 | .swagger-ui .Resizer.vertical.disabled { 1524 | display: none 1525 | } 1526 | 1527 | /*# sourceMappingURL=swagger-ui.css.map*/ 1528 | 1529 | /** 1530 | * Swagger UI Theme Overrides 1531 | * 1532 | * Theme: Outline 1533 | * Author: Mark Ostrander 1534 | * Github: https://github.com/ostranme/swagger-ui-themes 1535 | */ 1536 | 1537 | .swagger-ui .opblock.opblock-post { 1538 | border-color: #10a54a; 1539 | background: rgba(241, 241, 241, .1); 1540 | } 1541 | 1542 | .swagger-ui .opblock.opblock-post .opblock-summary-method { 1543 | background: #fafafa; 1544 | color: #10a54a; 1545 | border: solid 1px #10a54a; 1546 | } 1547 | 1548 | .swagger-ui .opblock.opblock-post .opblock-summary { 1549 | border-color: #DADFE1; 1550 | } 1551 | 1552 | .swagger-ui .opblock.opblock-put { 1553 | border-color: #c5862b; 1554 | background: rgba(241, 241, 241, .1); 1555 | } 1556 | 1557 | .swagger-ui .opblock.opblock-put .opblock-summary-method { 1558 | background: #fafafa; 1559 | color: #c5862b; 1560 | border: solid 1px #c5862b; 1561 | } 1562 | 1563 | .swagger-ui .opblock.opblock-put .opblock-summary { 1564 | border-color: #DADFE1; 1565 | } 1566 | 1567 | .swagger-ui .opblock.opblock-delete { 1568 | border-color: #a41e22; 1569 | background: rgba(241, 241, 241, .1); 1570 | } 1571 | 1572 | .swagger-ui .opblock.opblock-delete .opblock-summary-method { 1573 | background: #fafafa; 1574 | color: #a41e22; 1575 | border: solid 1px #a41e22; 1576 | } 1577 | 1578 | .swagger-ui .opblock.opblock-delete .opblock-summary { 1579 | border-color: #DADFE1; 1580 | } 1581 | 1582 | .swagger-ui .opblock.opblock-get { 1583 | border-color: #0f6ab4; 1584 | background: rgba(241, 241, 241, .1); 1585 | } 1586 | 1587 | .swagger-ui .opblock.opblock-get .opblock-summary-method { 1588 | background: #fafafa; 1589 | color: #0f6ab4; 1590 | border: solid 1px #0f6ab4; 1591 | } 1592 | 1593 | .swagger-ui .opblock.opblock-get .opblock-summary { 1594 | border-color: #DADFE1; 1595 | } 1596 | 1597 | .swagger-ui .opblock.opblock-patch { 1598 | border-color: #c5862b; 1599 | background: rgba(241, 241, 241, .1); 1600 | } 1601 | 1602 | .swagger-ui .opblock.opblock-patch .opblock-summary-method { 1603 | background: #fafafa; 1604 | color: #c5862b; 1605 | border: solid 1px #c5862b; 1606 | } 1607 | 1608 | .swagger-ui .opblock.opblock-patch .opblock-summary { 1609 | border-color: #DADFE1; 1610 | } 1611 | 1612 | .swagger-ui .opblock.opblock-head { 1613 | border-color: #0f6ab4; 1614 | background: rgba(241, 241, 241, .1); 1615 | } 1616 | 1617 | .swagger-ui .opblock.opblock-head .opblock-summary-method { 1618 | background: #fafafa; 1619 | color: #0f6ab4; 1620 | border: solid 1px #0f6ab4; 1621 | } 1622 | 1623 | .swagger-ui .opblock.opblock-head .opblock-summary { 1624 | border-color: #DADFE1; 1625 | } 1626 | 1627 | .swagger-ui .opblock.opblock-options { 1628 | border-color: #0f6ab4; 1629 | background: rgba(241, 241, 241, .1); 1630 | } 1631 | 1632 | .swagger-ui .opblock.opblock-options .opblock-summary-method { 1633 | background: #fafafa; 1634 | color: #0f6ab4; 1635 | border: solid 1px #0f6ab4; 1636 | } 1637 | 1638 | .swagger-ui .opblock.opblock-options .opblock-summary { 1639 | border-color: #DADFE1; 1640 | } 1641 | 1642 | .swagger-ui .info a { 1643 | font-size: 14px; 1644 | -webkit-transition: all .4s; 1645 | transition: all .4s; 1646 | font-family: Open Sans, sans-serif; 1647 | color: #0f6ab4; 1648 | } 1649 | 1650 | .swagger-ui .info a:hover { 1651 | color: #0f6ab4; 1652 | } 1653 | -------------------------------------------------------------------------------- /src/views/documentation.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ config('app.name') }} - G4T Swagger 9 | 10 | 11 | 13 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 96 | 97 | 98 | 119 | 120 | 121 | 122 |
123 | 124 | 125 | 126 | 127 | 191 | 192 | 193 | 194 | 197 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /src/views/issues.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Issues History 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 |
20 | 21 |
22 | 23 |
24 |

G4T Issues History

25 |
26 |
27 |
28 | 29 | 30 | @foreach ($issues as $issue) 31 |
32 |
33 |

[{{ $issue['date'] }}]

34 |

{{ $issue['message'] }}

35 |
36 |
37 | @endforeach 38 | 39 | 40 | 41 |
42 |
43 | 44 | 45 |
46 |
47 | 48 | 49 | --------------------------------------------------------------------------------