diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index b63406696..41decd23d 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -106,7 +106,7 @@ class ApiDocsGenerator return strpos($route->uri, 'api/') === 0; })->map(function ($route) { [$controller, $controllerMethod] = explode('@', $route->action['uses']); - $baseModelName = explode('/', $route->uri)[1]; + $baseModelName = explode('.', explode('/', $route->uri)[1])[0]; $shortName = $baseModelName . '-' . $controllerMethod; return [ 'name' => $shortName, diff --git a/app/Http/Controllers/Api/ApiDocsController.php b/app/Http/Controllers/Api/ApiDocsController.php index bfb0c1834..84ddd5215 100644 --- a/app/Http/Controllers/Api/ApiDocsController.php +++ b/app/Http/Controllers/Api/ApiDocsController.php @@ -13,9 +13,9 @@ class ApiDocsController extends ApiController public function display() { $docs = $this->getDocs(); - dd($docs); - // TODO - Build view for API docs - return view(''); + return view('api-docs.index', [ + 'docs' => $docs, + ]); } /** diff --git a/app/Http/Controllers/Api/BooksApiController.php b/app/Http/Controllers/Api/BooksApiController.php index 8c62b7d7d..fa174dfd3 100644 --- a/app/Http/Controllers/Api/BooksApiController.php +++ b/app/Http/Controllers/Api/BooksApiController.php @@ -2,8 +2,11 @@ use BookStack\Entities\Book; use BookStack\Entities\Repos\BookRepo; +use BookStack\Exceptions\NotifyException; use BookStack\Facades\Activity; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Http\Request; +use Illuminate\Validation\ValidationException; class BooksApiController extends ApiController { @@ -41,8 +44,8 @@ class BooksApiController extends ApiController } /** - * Create a new book. - * @throws \Illuminate\Validation\ValidationException + * Create a new book in the system. + * @throws ValidationException */ public function create(Request $request) { @@ -66,7 +69,7 @@ class BooksApiController extends ApiController /** * Update the details of a single book. - * @throws \Illuminate\Validation\ValidationException + * @throws ValidationException */ public function update(Request $request, string $id) { @@ -81,9 +84,9 @@ class BooksApiController extends ApiController } /** - * Delete a book from the system. - * @throws \BookStack\Exceptions\NotifyException - * @throws \Illuminate\Contracts\Container\BindingResolutionException + * Delete a single book from the system. + * @throws NotifyException + * @throws BindingResolutionException */ public function delete(string $id) { diff --git a/resources/js/components/details-highlighter.js b/resources/js/components/details-highlighter.js new file mode 100644 index 000000000..18c5165fa --- /dev/null +++ b/resources/js/components/details-highlighter.js @@ -0,0 +1,18 @@ +import Code from "../services/code" +class DetailsHighlighter { + + constructor(elem) { + this.elem = elem; + this.dealtWith = false; + elem.addEventListener('toggle', this.onToggle.bind(this)); + } + + onToggle() { + if (this.dealtWith) return; + + Code.highlightWithin(this.elem); + this.dealtWith = true; + } +} + +export default DetailsHighlighter; \ No newline at end of file diff --git a/resources/js/components/index.js b/resources/js/components/index.js index bbe059898..d3ba539dd 100644 --- a/resources/js/components/index.js +++ b/resources/js/components/index.js @@ -30,6 +30,7 @@ import settingColorPicker from "./setting-color-picker"; import entityPermissionsEditor from "./entity-permissions-editor"; import templateManager from "./template-manager"; import newUserPassword from "./new-user-password"; +import detailsHighlighter from "./details-highlighter"; const componentMapping = { 'dropdown': dropdown, @@ -64,6 +65,7 @@ const componentMapping = { 'entity-permissions-editor': entityPermissionsEditor, 'template-manager': templateManager, 'new-user-password': newUserPassword, + 'details-highlighter': detailsHighlighter, }; window.components = {}; diff --git a/resources/js/services/code.js b/resources/js/services/code.js index 26dee5bfb..834a547e3 100644 --- a/resources/js/services/code.js +++ b/resources/js/services/code.js @@ -87,9 +87,20 @@ const modeMap = { * Highlight pre elements on a page */ function highlight() { - let codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre'); - for (let i = 0; i < codeBlocks.length; i++) { - highlightElem(codeBlocks[i]); + const codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre'); + for (const codeBlock of codeBlocks) { + highlightElem(codeBlock); + } +} + +/** + * Highlight all code blocks within the given parent element + * @param {HTMLElement} parent + */ +function highlightWithin(parent) { + const codeBlocks = parent.querySelectorAll('pre'); + for (const codeBlock of codeBlocks) { + highlightElem(codeBlock); } } @@ -308,6 +319,7 @@ function getMetaKey() { export default { highlight: highlight, + highlightWithin: highlightWithin, wysiwygView: wysiwygView, popupEditor: popupEditor, setMode: setMode, diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index 2cb17a18d..cc42dc736 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -236,4 +236,26 @@ .tag-list div:last-child .tag-item { margin-bottom: 0; +} + +/** + * API Docs + */ +.api-method { + font-size: 0.75rem; + background-color: #888; + padding: $-xs; + line-height: 1.3; + opacity: 0.7; + vertical-align: top; + border-radius: 3px; + color: #FFF; + display: inline-block; + min-width: 60px; + text-align: center; + font-weight: bold; + &[data-method="GET"] { background-color: #077b70 } + &[data-method="POST"] { background-color: #cf4d03 } + &[data-method="PUT"] { background-color: #0288D1 } + &[data-method="DELETE"] { background-color: #ab0f0e } } \ No newline at end of file diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index cf78c162b..77e0773eb 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -213,6 +213,18 @@ blockquote { } } +.text-mono { + font-family: $mono; +} + +.text-uppercase { + text-transform: uppercase; +} + +.text-capitals { + text-transform: capitalize; +} + .code-base { background-color: #F8F8F8; font-size: 0.80em; diff --git a/resources/views/api-docs/index.blade.php b/resources/views/api-docs/index.blade.php new file mode 100644 index 000000000..181bcd746 --- /dev/null +++ b/resources/views/api-docs/index.blade.php @@ -0,0 +1,51 @@ +@extends('simple-layout') + +@section('body') + +
+ +
+ +
+ @foreach($docs as $model => $endpoints) +

{{ $model }}

+ + @foreach($endpoints as $endpoint) + + @endforeach + @endforeach +
+ +
+ @foreach($docs as $model => $endpoints) +
+

{{ $model }}

+ + @foreach($endpoints as $endpoint) +
+ {{ $endpoint['method'] }} + {{ url($endpoint['uri']) }} +
+

{{ $endpoint['description'] ?? '' }}

+ @if($endpoint['example_response'] ?? false) +
+ Example Response +
{{ $endpoint['example_response'] }}
+
+
+ @endif + @endforeach +
+ @endforeach +
+ +
+ + +
+@stop \ No newline at end of file