diff --git a/README.md b/README.md index 98367ea5..5c1b103c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Swagger-generated API Reference Documentation ## Deployment -## tl;dr +#### tl;dr ```html @@ -72,6 +72,13 @@ For npm: ## Configuration +#### Swagger vendor extensions +ReDoc makes use of the following [vendor extensions](http://swagger.io/specification/#vendorExtensions): +* [`x-logo`](docs/redoc-vendor-extensions.md#x-logo) - is used to specify API logo +* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for handling out common things like Pagination, Rate-Limits, etc +* [`x-code-samples`](docs/redoc-vendor-extensions.md#x-code-samples) - specify operation code samples + +#### Options * `spec-url` - relative or absolute url to your spec file * `scroll-y-offset` - If set, specifies a vertical scroll-offset. This is often useful when there are fixed positioned elements at the top of the page, such as navbars, headers etc. `scroll-y-offset` can be specified in various ways: @@ -85,7 +92,7 @@ Instead of adding `spec-url` attribute to the `` element you can initiali Redoc.init(specUrl, options) ``` -`options` is javascript object with camel-cased versions of options names as the keys. For example: +`options` is javascript object with camel-cased version of options names as the keys. For example: ```js Redoc.init('http://petstore.swagger.io/v2/swagger.json', { scrollYOffset: 50 diff --git a/build/tasks/build.js b/build/tasks/build.js index 18677e6e..2f14a46f 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -87,9 +87,6 @@ function concatDeps(deps, file) { function bundle(outputFile, minify, cb) { fs.existsSync('dist') || fs.mkdirSync('dist'); var builder = new Builder('./', 'system.config.js'); - builder.config({ - separateCSS: true - }); builder .buildStatic(path.join(paths.tmp, paths.sourceEntryPoint), diff --git a/demo/index.html b/demo/index.html index f7889511..1d480d20 100644 --- a/demo/index.html +++ b/demo/index.html @@ -9,12 +9,12 @@ - + diff --git a/demo/swagger.json b/demo/swagger.json deleted file mode 100644 index 2a126a55..00000000 --- a/demo/swagger.json +++ /dev/null @@ -1,892 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", - "version": "1.0.0", - "title": "Swagger Petstore", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "email": "apiteam@swagger.io" - }, - "x-logo": { - "url": "https://rebilly.github.io/ReDoc/petstore-logo.png" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } - }, - "host": "petstore.swagger.io", - "basePath": "/v2", - "tags": [{ - "name": "Pagination", - "x-traitTag": true, - "description": "Sometimes you just can't get enough. For this reason, we've provided a convenient way to access more data in any request for sequential data. Simply call the url in the next_url parameter and we'll respond with the next set of data.\n```json\n{\n ...\n \"pagination\": {\n \"next_url\": \"https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296\",\n \"next_max_id\": \"13872296\"\n }\n}\n```\n On views where pagination is present, we also support the `count` parameter. Simply set this to the number of items you'd like to receive. Note that the default values should be fine for most applications - but if you decide to increase this number there is a maximum value defined on each endpoint.", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - },{ - "name": "JSONP", - "x-traitTag": true, - "description": "If you're writing an AJAX application, and you'd like to wrap our response with a callback, all you have to do is specify a callback parameter with any API call:\n```\n https://api.instagram.com/v1/tags/coffee/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&callback=callbackFunction\n```\nWould respond with:\n```js\ncallbackFunction({\n ...\n});\n``` \n > Example of markdown blockquote", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - },{ - "name": "pet", - "description": "Everything about your Pets", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - }, { - "name": "store", - "description": "Access to Petstore orders" - }, { - "name": "user", - "description": "Operations about user", - "externalDocs": { - "description": "Find out more about our store", - "url": "http://swagger.io" - } - }], - "schemes": ["http"], - "paths": { - "/pet": { - "post": { - "tags": ["pet"], - "summary": "Add a new pet to the store", - "description": "", - "operationId": "addPet", - "consumes": ["application/json", "application/xml"], - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "Pet object that needs to be added to the store", - "required": true, - "schema": { - "$ref": "#/definitions/Pet" - } - }], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - }, - "put": { - "tags": ["pet"], - "summary": "Update an existing pet", - "description": "", - "operationId": "updatePet", - "consumes": ["application/json", "application/xml"], - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "Pet object that needs to be added to the store", - "required": true, - "schema": { - "$ref": "#/definitions/Pet" - } - }], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - }, - "405": { - "description": "Validation exception" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/findByStatus": { - "get": { - "tags": ["pet", "Pagination", "JSONP"], - "summary": "Finds Pets by status", - "description": "Multiple status values can be provided with comma seperated strings", - "operationId": "findPetsByStatus", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "status", - "in": "query", - "description": "Status values that need to be considered for filter", - "required": true, - "type": "array", - "items": { - "type": "string", - "enum": ["available", "pending", "sold"], - "default": "available" - }, - "collectionFormat": "csv" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Pet" - } - } - }, - "400": { - "description": "Invalid status value" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/findByTags": { - "get": { - "tags": ["pet", "Pagination", "JSONP"], - "summary": "Finds Pets by tags", - "description": "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", - "operationId": "findPetsByTags", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "tags", - "in": "query", - "description": "Tags to filter by", - "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Pet" - } - } - }, - "400": { - "description": "Invalid tag value" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/{petId}": { - "get": { - "tags": ["pet", "JSONP"], - "summary": "Find pet by ID", - "description": "Returns a single pet", - "operationId": "getPetById", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "petId", - "in": "path", - "description": "ID of pet to return", - "required": true, - "type": "integer", - "format": "int64" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Pet" - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - } - }, - "security": [{ - "api_key": [] - }] - }, - "post": { - "tags": ["pet"], - "summary": "Updates a pet in the store with form data", - "description": "", - "operationId": "updatePetWithForm", - "consumes": ["application/x-www-form-urlencoded"], - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "petId", - "in": "path", - "description": "ID of pet that needs to be updated", - "required": true, - "type": "integer", - "format": "int64" - }, { - "name": "name", - "in": "formData", - "description": "Updated name of the pet", - "required": false, - "type": "string" - }, { - "name": "status", - "in": "formData", - "description": "Updated status of the pet", - "required": false, - "type": "string" - }], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - }, - "delete": { - "tags": ["pet"], - "summary": "Deletes a pet", - "description": "", - "operationId": "deletePet", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "api_key", - "in": "header", - "required": false, - "type": "string" - }, { - "name": "petId", - "in": "path", - "description": "Pet id to delete", - "required": true, - "type": "integer", - "format": "int64" - }], - "responses": { - "400": { - "description": "Invalid pet value" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/{petId}/uploadImage": { - "post": { - "tags": ["pet"], - "summary": "uploads an image", - "description": "", - "operationId": "uploadFile", - "consumes": ["multipart/form-data"], - "produces": ["application/json"], - "parameters": [{ - "name": "petId", - "in": "path", - "description": "ID of pet to update", - "required": true, - "type": "integer", - "format": "int64" - }, { - "name": "additionalMetadata", - "in": "formData", - "description": "Additional data to pass to server", - "required": false, - "type": "string" - }, { - "name": "file", - "in": "formData", - "description": "file to upload", - "required": false, - "type": "file" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/ApiResponse" - } - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/store/inventory": { - "get": { - "tags": ["store", "JSONP"], - "summary": "Returns pet inventories by status", - "description": "Returns a map of status codes to quantities", - "operationId": "getInventory", - "produces": ["application/json"], - "parameters": [], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int32" - } - } - } - }, - "security": [{ - "api_key": [] - }] - } - }, - "/store/order": { - "post": { - "tags": ["store"], - "summary": "Place an order for a pet", - "description": "", - "operationId": "placeOrder", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "order placed for purchasing the pet", - "required": true, - "schema": { - "$ref": "#/definitions/Order" - } - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Order" - } - }, - "400": { - "description": "Invalid Order" - } - } - } - }, - "/store/order/{orderId}": { - "get": { - "tags": ["store", "JSONP"], - "summary": "Find purchase order by ID", - "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", - "operationId": "getOrderById", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "orderId", - "in": "path", - "description": "ID of pet that needs to be fetched", - "required": true, - "type": "integer", - "maximum": 5.0, - "minimum": 1.0, - "format": "int64" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Order" - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - }, - "delete": { - "tags": ["store"], - "summary": "Delete purchase order by ID", - "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", - "operationId": "deleteOrder", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "orderId", - "in": "path", - "description": "ID of the order that needs to be deleted", - "required": true, - "type": "string", - "minimum": 1.0 - }], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - } - }, - "/user": { - "post": { - "tags": ["user"], - "summary": "Create user", - "description": "This can only be done by the logged in user.", - "operationId": "createUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "Created user object", - "required": true, - "schema": { - "$ref": "#/definitions/User" - } - }], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/createWithArray": { - "post": { - "tags": ["user"], - "summary": "Creates list of users with given input array", - "description": "", - "operationId": "createUsersWithArrayInput", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "List of user object", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/User" - } - } - }], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/createWithList": { - "post": { - "tags": ["user"], - "summary": "Creates list of users with given input array", - "description": "", - "operationId": "createUsersWithListInput", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "List of user object", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/User" - } - } - }], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/login": { - "get": { - "tags": ["user"], - "summary": "Logs user into the system", - "description": "", - "operationId": "loginUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "query", - "description": "The user name for login", - "required": true, - "type": "string" - }, { - "name": "password", - "in": "query", - "description": "The password for login in clear text", - "required": true, - "type": "string" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "string" - }, - "headers": { - "X-Rate-Limit": { - "type": "integer", - "format": "int32", - "description": "calls per hour allowed by the user" - }, - "X-Expires-After": { - "type": "string", - "format": "date-time", - "description": "date in UTC when toekn expires" - } - } - }, - "400": { - "description": "Invalid username/password supplied" - } - } - } - }, - "/user/logout": { - "get": { - "tags": ["user"], - "summary": "Logs out current logged in user session", - "description": "", - "operationId": "logoutUser", - "produces": ["application/xml", "application/json"], - "parameters": [], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/{username}": { - "get": { - "tags": ["user", "JSONP"], - "summary": "Get user by user name", - "description": "", - "operationId": "getUserByName", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "path", - "description": "The name that needs to be fetched. Use user1 for testing. ", - "required": true, - "type": "string" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/User" - } - }, - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "put": { - "tags": ["user"], - "summary": "Updated user", - "description": "This can only be done by the logged in user.", - "operationId": "updateUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "path", - "description": "name that need to be deleted", - "required": true, - "type": "string" - }, { - "in": "body", - "name": "body", - "description": "Updated user object", - "required": true, - "schema": { - "$ref": "#/definitions/User" - } - }], - "responses": { - "400": { - "description": "Invalid user supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "delete": { - "tags": ["user"], - "summary": "Delete user", - "description": "This can only be done by the logged in user.", - "operationId": "deleteUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "path", - "description": "The name that needs to be deleted", - "required": true, - "type": "string" - }], - "responses": { - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - } - } - }, - "securityDefinitions": { - "petstore_auth": { - "type": "oauth2", - "authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog", - "flow": "implicit", - "scopes": { - "write:pets": "modify pets in your account", - "read:pets": "read your pets" - } - }, - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "header" - } - }, - "definitions": { - "Order": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "petId": { - "type": "integer", - "format": "int64" - }, - "quantity": { - "type": "integer", - "format": "int32" - }, - "shipDate": { - "type": "string", - "format": "date-time" - }, - "status": { - "type": "string", - "description": "Order Status", - "enum": ["placed", "approved", "delivered"] - }, - "complete": { - "type": "boolean", - "default": false - } - }, - "xml": { - "name": "Order" - } - }, - "User": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "username": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "email": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "userStatus": { - "type": "integer", - "format": "int32", - "description": "User Status" - } - }, - "xml": { - "name": "User" - } - }, - "Category": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "Category" - } - }, - "Tag": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "Tag" - } - }, - "Pet": { - "type": "object", - "required": ["name", "photoUrls"], - "discriminator": "petType", - "properties": { - "petType": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "category": { - "$ref": "#/definitions/Category" - }, - "name": { - "type": "string", - "example": "doggie" - }, - "photoUrls": { - "type": "array", - "xml": { - "name": "photoUrl", - "wrapped": true - }, - "items": { - "type": "string" - } - }, - "tags": { - "type": "array", - "xml": { - "name": "tag", - "wrapped": true - }, - "items": { - "$ref": "#/definitions/Tag" - } - }, - "status": { - "type": "string", - "description": "pet status in the store", - "enum": ["available", "pending", "sold"] - } - }, - "xml": { - "name": "Pet" - } - }, - "Cat": { - "description": "A representation of a cat", - "allOf": [ - { - "$ref": "#/definitions/Pet" - }, - { - "type": "object", - "properties": { - "huntingSkill": { - "type": "string", - "description": "The measured skill for hunting", - "default": "lazy", - "enum": [ - "clueless", - "lazy", - "adventurous", - "aggressive" - ] - } - }, - "required": [ - "huntingSkill" - ] - } - ] - }, - "Dog": { - "description": "A representation of a dog", - "allOf": [ - { - "$ref": "#/definitions/Pet" - }, - { - "type": "object", - "properties": { - "packSize": { - "type": "integer", - "format": "int32", - "description": "the size of the pack the dog is from", - "default": 0, - "minimum": 0 - } - }, - "required": [ - "packSize" - ] - } - ] - }, - "ApiResponse": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32" - }, - "type": { - "type": "string" - }, - "message": { - "type": "string" - } - } - } - }, - "externalDocs": { - "description": "Find out more about Swagger", - "url": "http://swagger.io" - } -} diff --git a/demo/swagger.yml b/demo/swagger.yml new file mode 100644 index 00000000..0a41c2ee --- /dev/null +++ b/demo/swagger.yml @@ -0,0 +1,862 @@ +--- + swagger: "2.0" + info: + description: "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters." + version: "1.0.0" + title: "Swagger Petstore" + termsOfService: "http://swagger.io/terms/" + contact: + email: "apiteam@swagger.io" + x-logo: + url: "https://rebilly.github.io/ReDoc/petstore-logo.png" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" + host: "petstore.swagger.io" + basePath: "/v2" + tags: + - + name: "Pagination" + x-traitTag: true + description: |- + Sometimes you just can't get enough. For this reason, we've provided a convenient way to access more data in + any request for sequential data. Simply call the url in the next_url parameter and we'll respond with the next + set of data. + + ```json + { + ... + "pagination": { + "next_url": "https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296", + "next_max_id": "13872296" + } + } + ``` + + On views where pagination is present, we also support the `count` parameter. + Simply set this to the number of items you'd like to receive. Note that the default values + should be fine for most applications - but if you decide to increase this number there is a maximum value + defined on each endpoint. + externalDocs: + description: "Find out more" + url: "http://swagger.io" + - + name: "JSONP" + x-traitTag: true + description: |- + If you're writing an AJAX application, and you'd like to wrap our response with a callback, + all you have to do is specify a callback parameter with any API call: + + ``` + https://api.instagram.com/v1/tags/coffee/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&callback=callbackFunction + ``` + Would respond with: + + ```js + callbackFunction({ + ... + }); + ``` + + > Example of markdown blockquote + externalDocs: + description: "Find out more" + url: "http://swagger.io" + - + name: "pet" + description: "Everything about your Pets" + externalDocs: + description: "Find out more" + url: "http://swagger.io" + - + name: "store" + description: "Access to Petstore orders" + - + name: "user" + description: "Operations about user" + externalDocs: + description: "Find out more about our store" + url: "http://swagger.io" + schemes: + - "http" + paths: + /pet: + post: + tags: + - "pet" + summary: "Add a new pet to the store" + description: "" + operationId: "addPet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 405: + description: "Invalid input" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + x-code-samples: + - + lang: PHP + source: |- + $form = new \PetStore\Entities\Pet(); + $form->setPetType("Dog"); + $form->setName("Rex"); + // set other fields + + try { + $pet = $client->pets()->create($form); + } catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); + } + - + lang: C# + source: |- + PetStore.v1.Pet pet = new PetStore.v1.Pet(); + pet.setApiKey("your api key"); + pet.petType = PetStore.v1.Pet.TYPE_DOG; + pet.name = "Rex"; + // set other fields + + PetStoreResponse response = pet.create(); + if (response.statusCode == HttpStatusCode.Created) + { + // Successfully created + } + else + { + // Something wrong -- check response for errors + Console.WriteLine(response.getRawResponse()); + } + put: + tags: + - "pet" + summary: "Update an existing pet" + description: "" + operationId: "updatePet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + 405: + description: "Validation exception" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByStatus: + get: + tags: + - "pet" + - "Pagination" + - "JSONP" + summary: "Finds Pets by status" + description: "Multiple status values can be provided with comma seperated strings" + operationId: "findPetsByStatus" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "status" + in: "query" + description: "Status values that need to be considered for filter" + required: true + type: "array" + items: + type: "string" + enum: + - "available" + - "pending" + - "sold" + default: "available" + collectionFormat: "csv" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid status value" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByTags: + get: + tags: + - "pet" + - "Pagination" + - "JSONP" + summary: "Finds Pets by tags" + description: "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing." + operationId: "findPetsByTags" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "tags" + in: "query" + description: "Tags to filter by" + required: true + type: "array" + items: + type: "string" + collectionFormat: "csv" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid tag value" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/{petId}: + get: + tags: + - "pet" + - "JSONP" + summary: "Find pet by ID" + description: "Returns a single pet" + operationId: "getPetById" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "petId" + in: "path" + description: "ID of pet to return" + required: true + type: "integer" + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Pet" + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + security: + - + api_key: [] + post: + tags: + - "pet" + summary: "Updates a pet in the store with form data" + description: "" + operationId: "updatePetWithForm" + consumes: + - "application/x-www-form-urlencoded" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "petId" + in: "path" + description: "ID of pet that needs to be updated" + required: true + type: "integer" + format: "int64" + - + name: "name" + in: "formData" + description: "Updated name of the pet" + required: false + type: "string" + - + name: "status" + in: "formData" + description: "Updated status of the pet" + required: false + type: "string" + responses: + 405: + description: "Invalid input" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + delete: + tags: + - "pet" + summary: "Deletes a pet" + description: "" + operationId: "deletePet" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "api_key" + in: "header" + required: false + type: "string" + - + name: "petId" + in: "path" + description: "Pet id to delete" + required: true + type: "integer" + format: "int64" + responses: + 400: + description: "Invalid pet value" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/{petId}/uploadImage: + post: + tags: + - "pet" + summary: "uploads an image" + description: "" + operationId: "uploadFile" + consumes: + - "multipart/form-data" + produces: + - "application/json" + parameters: + - + name: "petId" + in: "path" + description: "ID of pet to update" + required: true + type: "integer" + format: "int64" + - + name: "additionalMetadata" + in: "formData" + description: "Additional data to pass to server" + required: false + type: "string" + - + name: "file" + in: "formData" + description: "file to upload" + required: false + type: "file" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /store/inventory: + get: + tags: + - "store" + - "JSONP" + summary: "Returns pet inventories by status" + description: "Returns a map of status codes to quantities" + operationId: "getInventory" + produces: + - "application/json" + parameters: [] + responses: + 200: + description: "successful operation" + schema: + type: "object" + additionalProperties: + type: "integer" + format: "int32" + security: + - + api_key: [] + /store/order: + post: + tags: + - "store" + summary: "Place an order for a pet" + description: "" + operationId: "placeOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "order placed for purchasing the pet" + required: true + schema: + $ref: "#/definitions/Order" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid Order" + /store/order/{orderId}: + get: + tags: + - "store" + - "JSONP" + summary: "Find purchase order by ID" + description: "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions" + operationId: "getOrderById" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "orderId" + in: "path" + description: "ID of pet that needs to be fetched" + required: true + type: "integer" + maximum: 5 + minimum: 1 + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + delete: + tags: + - "store" + summary: "Delete purchase order by ID" + description: "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors" + operationId: "deleteOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "orderId" + in: "path" + description: "ID of the order that needs to be deleted" + required: true + type: "string" + minimum: 1 + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + /user: + post: + tags: + - "user" + summary: "Create user" + description: "This can only be done by the logged in user." + operationId: "createUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "Created user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithArray: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithArrayInput" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithList: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithListInput" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/login: + get: + tags: + - "user" + summary: "Logs user into the system" + description: "" + operationId: "loginUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "query" + description: "The user name for login" + required: true + type: "string" + - + name: "password" + in: "query" + description: "The password for login in clear text" + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + type: "string" + headers: + X-Rate-Limit: + type: "integer" + format: "int32" + description: "calls per hour allowed by the user" + X-Expires-After: + type: "string" + format: "date-time" + description: "date in UTC when toekn expires" + 400: + description: "Invalid username/password supplied" + /user/logout: + get: + tags: + - "user" + summary: "Logs out current logged in user session" + description: "" + operationId: "logoutUser" + produces: + - "application/xml" + - "application/json" + parameters: [] + responses: + default: + description: "successful operation" + /user/{username}: + get: + tags: + - "user" + - "JSONP" + summary: "Get user by user name" + description: "" + operationId: "getUserByName" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "path" + description: "The name that needs to be fetched. Use user1 for testing. " + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/User" + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + put: + tags: + - "user" + summary: "Updated user" + description: "This can only be done by the logged in user." + operationId: "updateUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "path" + description: "name that need to be deleted" + required: true + type: "string" + - + in: "body" + name: "body" + description: "Updated user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + 400: + description: "Invalid user supplied" + 404: + description: "User not found" + delete: + tags: + - "user" + summary: "Delete user" + description: "This can only be done by the logged in user." + operationId: "deleteUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "path" + description: "The name that needs to be deleted" + required: true + type: "string" + responses: + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + securityDefinitions: + petstore_auth: + type: "oauth2" + authorizationUrl: "http://petstore.swagger.io/api/oauth/dialog" + flow: "implicit" + scopes: + write:pets: "modify pets in your account" + read:pets: "read your pets" + api_key: + type: "apiKey" + name: "api_key" + in: "header" + definitions: + Order: + type: "object" + properties: + id: + type: "integer" + format: "int64" + petId: + type: "integer" + format: "int64" + quantity: + type: "integer" + format: "int32" + shipDate: + type: "string" + format: "date-time" + status: + type: "string" + description: "Order Status" + enum: + - "placed" + - "approved" + - "delivered" + complete: + type: "boolean" + default: false + xml: + name: "Order" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + username: + type: "string" + firstName: + type: "string" + lastName: + type: "string" + email: + type: "string" + password: + type: "string" + phone: + type: "string" + userStatus: + type: "integer" + format: "int32" + description: "User Status" + xml: + name: "User" + Category: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Category" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Tag" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + - "petType" + discriminator: "petType" + properties: + petType: + type: "string" + id: + type: "integer" + format: "int64" + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + xml: + name: "Pet" + Cat: + description: "A representation of a cat" + allOf: + - + $ref: "#/definitions/Pet" + - + type: "object" + properties: + huntingSkill: + type: "string" + description: "The measured skill for hunting" + default: "lazy" + enum: + - "clueless" + - "lazy" + - "adventurous" + - "aggressive" + required: + - "huntingSkill" + Dog: + description: "A representation of a dog" + allOf: + - + $ref: "#/definitions/Pet" + - + type: "object" + properties: + packSize: + type: "integer" + format: "int32" + description: "the size of the pack the dog is from" + default: 0 + minimum: 0 + required: + - "packSize" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" + externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io" diff --git a/docs/redoc-vendor-extensions.md b/docs/redoc-vendor-extensions.md new file mode 100644 index 00000000..e6dcac25 --- /dev/null +++ b/docs/redoc-vendor-extensions.md @@ -0,0 +1,105 @@ +# ReDoc vendor extensions +ReDoc makes use of the following [vendor extensions](http://swagger.io/specification/#vendorExtensions) + +### [Info Object](http://swagger.io/specification/#infoObject) vendor extensions + +#### x-logo +| Field Name | Type | Description +| :------------- | :------: | +| x-logo | [Logo Object](#logoObject) | The information about API logo + +##### Usage in Redoc +`x-logo` is used to specify API logo. The corresponding image are displayed just above side-menu. + +#### Logo Object +The information about API logo +##### Fixed fields +| Field Name | Type | Description +| :---------- | :------: | +| url | string | The URL pointing to the spec logo. MUST be in the format of a URL +| backgroundColor | string | background color to be used. MUST be in [CSS color syntax](https://developer.mozilla.org/en/docs/Web/CSS/color) + + +##### x-logo example +```yaml +{ + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "x-logo": { + "url": "https://rebilly.github.io/ReDoc/petstore-logo.png", + "backgroundColor": "white" + } + } +} +``` +```yaml +{ + info: + version: "1.0.0" + title: "Swagger Petstore" + x-logo: + url: "https://rebilly.github.io/ReDoc/petstore-logo.png" + backgroundColor: "white" +} +``` + + + +### [Tag object](http://swagger.io/specification/#tagObject) vendor extensions + +#### x-traitTag +| Field Name | Type | Description +| :------------- | :------: | +| x-traitTag | boolean | In Swagger two operations can have multiply tags. This property distinguish between tags that are used to group operations (default) from tags that are used to mark operation with certain trait (`true` value) + +##### Usage in Redoc +Tags that have `x-traitTag` set to `true` are listed in side-menu but don't have any subitems (operations). Tag `description` is rendered as well. +This is useful for handling out common things like Pagination, Rate-Limits, etc. + +##### x-traitTag example +```json +{ + "name": "Pagination", + "description": "Pagination description (can use markdown syntax)", + "x-traitTag": true +} +``` +```yaml +name: Pagination +description: Pagination description (can use markdown syntax) +x-traitTag: true +``` + +### [Operation Object](http://swagger.io/specification/#operationObject) vendor extensions + +#### x-code-samples +| Field Name | Type | Description +| :------------- | :------: | +| x-code-samples | [[Code Sample Object](#codeSampleObject)] | A list of code samples associated with operation + +##### Usage in ReDoc +x-code-samples are rendered on the right panel of ReDoc + +#### Code Sample Object +Operation code sample +##### Fixed fields +| Field Name | Type | Description +| :---------- | :------: | :----------- +| lang | string | Code sample language. Value should be one of the following [list](https://github.com/github/linguist/blob/master/lib/linguist/popular.yml) +| source | string | Code sample source code + + +##### Code Sample Object example +```yaml +{ + "lang": "JavaScript", + "source": "console.log('Hello World');" +} +``` +```yaml +{ + lang: JavaScript + source: console.log('Hello World'); +} +``` diff --git a/karma.conf.js b/karma.conf.js index 3fbf51b8..537dd917 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -55,7 +55,7 @@ module.exports = function (config) { jspm: { config: 'system.config.js', loadFiles: ['tests/unit/*.spec.js', 'tests/helpers.js', 'lib/**/*.js'], - serveFiles: ['tests/schemas/**/*.json', 'lib/**/*.html', '.tmp/lib/**/*.css'], + serveFiles: ['tests/schemas/**/*.json','tests/schemas/**/*.yml', 'lib/**/*.html', '.tmp/lib/**/*.css'], nocache: true }, diff --git a/lib/common/components/StickySidebar/sticky-sidebar.js b/lib/common/components/StickySidebar/sticky-sidebar.js index c0f2cd1b..ad99a264 100644 --- a/lib/common/components/StickySidebar/sticky-sidebar.js +++ b/lib/common/components/StickySidebar/sticky-sidebar.js @@ -47,7 +47,7 @@ export default class StickySidebar { } get scrollY() { - return (this.scrollParent.pageYOffset !== null) ? this.scrollParent.pageYOffset : this.scrollParent.scrollTop; + return (this.scrollParent.pageYOffset != null) ? this.scrollParent.pageYOffset : this.scrollParent.scrollTop; } ngOnInit() { diff --git a/lib/components/ApiLogo/api-logo.spec.js b/lib/components/ApiLogo/api-logo.spec.js index 0f438c58..e2ebb319 100644 --- a/lib/components/ApiLogo/api-logo.spec.js +++ b/lib/components/ApiLogo/api-logo.spec.js @@ -53,7 +53,7 @@ describe('Redoc components', () => { expect(imgElement).toBeNull(); // update schemaUrl to load other schema in the next test - schemaUrl = '/tests/schemas/extended-petstore.json'; + schemaUrl = '/tests/schemas/extended-petstore.yml'; }); it('should load values from spec and use transparent bgColor by default', () => { diff --git a/lib/components/Method/method.html b/lib/components/Method/method.html index 697a213b..e677c448 100644 --- a/lib/components/Method/method.html +++ b/lib/components/Method/method.html @@ -18,8 +18,8 @@
-
Body sample
- + +
diff --git a/lib/components/Method/method.js b/lib/components/Method/method.js index 05674deb..13aa8178 100644 --- a/lib/components/Method/method.js +++ b/lib/components/Method/method.js @@ -6,12 +6,13 @@ import ParamsList from '../ParamsList/params-list'; import ResponsesList from '../ResponsesList/responses-list'; import ResponsesSamples from '../ResponsesSamples/responses-samples'; import SchemaSample from '../SchemaSample/schema-sample'; +import RequestSamples from '../RequestSamples/request-samples'; @RedocComponent({ selector: 'method', templateUrl: './lib/components/Method/method.html', styleUrls: ['./lib/components/Method/method.css'], - directives: [ParamsList, ResponsesList, ResponsesSamples, SchemaSample], + directives: [ParamsList, ResponsesList, ResponsesSamples, SchemaSample, RequestSamples], inputs: ['tag'] }) export default class Method extends BaseComponent { diff --git a/lib/components/Method/method.spec.js b/lib/components/Method/method.spec.js index c6c87df9..5385c9c8 100644 --- a/lib/components/Method/method.spec.js +++ b/lib/components/Method/method.spec.js @@ -23,7 +23,7 @@ describe('Redoc components', () => { ]); beforeEach(injectAsync([TestComponentBuilder, SchemaManager], (tcb, schemaMgr) => { builder = tcb; - return schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => null, (err) => { throw err; }); + return schemaMgr.load('/tests/schemas/extended-petstore.yml').then(() => null, (err) => { throw err; }); })); beforeEach((done) => { builder.createAsync(TestApp).then(fixture => { diff --git a/lib/components/Redoc/redoc.spec.js b/lib/components/Redoc/redoc.spec.js index e332965b..d271bcd4 100644 --- a/lib/components/Redoc/redoc.spec.js +++ b/lib/components/Redoc/redoc.spec.js @@ -28,7 +28,7 @@ describe('Redoc components', () => { ]); beforeEach(injectAsync([TestComponentBuilder, SchemaManager], (tcb, schemaMgr) => { builder = tcb; - return schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => null, (err) => { throw err; }); + return schemaMgr.load('/tests/schemas/extended-petstore.yml').then(() => null, (err) => { throw err; }); })); @@ -134,7 +134,7 @@ describe('Redoc components', () => { xit('should init redoc', (done) => { var node = document.createElement('redoc'); document.body.appendChild(node); - let res = Redoc.init('/tests/schemas/extended-petstore.json'); + let res = Redoc.init('/tests/schemas/extended-petstore.yml'); res.then(() => { done(); }, () => { done.fail('Error handler should not been called'); }); diff --git a/lib/components/RequestSamples/request-samples.html b/lib/components/RequestSamples/request-samples.html new file mode 100644 index 00000000..2f71bdd2 --- /dev/null +++ b/lib/components/RequestSamples/request-samples.html @@ -0,0 +1,10 @@ +
Request samples
+ + + + + + +

+  
+
diff --git a/lib/components/RequestSamples/request-samples.js b/lib/components/RequestSamples/request-samples.js new file mode 100644 index 00000000..6bebaa32 --- /dev/null +++ b/lib/components/RequestSamples/request-samples.js @@ -0,0 +1,27 @@ +'use strict'; + +import {RedocComponent, BaseComponent} from '../base'; +import JsonPointer from '../../utils/JsonPointer'; +import {Tabs, Tab} from '../../common/components/Tabs/tabs'; +import SchemaSample from '../SchemaSample/schema-sample'; +import {PrismPipe} from '../../utils/pipes'; + +@RedocComponent({ + selector: 'request-samples', + templateUrl: './lib/components/RequestSamples/request-samples.html', + styleUrls: ['./lib/components/RequestSamples/request-samples.css'], + directives: [SchemaSample, Tabs, Tab], + inputs: ['bodySchemaPtr'], + pipes: [PrismPipe] +}) +export default class RequestSamples extends BaseComponent { + constructor(schemaMgr) { + super(schemaMgr); + } + + prepareModel() { + this.data = {}; + this.data.bodySchemaPtr = JsonPointer.join(this.bodySchemaPtr, 'schema'); + this.data.samples = this.componentSchema['x-code-samples'] || []; + } +} diff --git a/lib/components/RequestSamples/request-samples.scss b/lib/components/RequestSamples/request-samples.scss new file mode 100644 index 00000000..4270dc84 --- /dev/null +++ b/lib/components/RequestSamples/request-samples.scss @@ -0,0 +1,34 @@ +@import '../../common/styles/variables'; + +header { + font-size: 16px; + margin: 5px 0; + color: $sample-panel-headers-color; + text-transform: uppercase; + font-weight: normal; +} + +:host > tabs > ul li { + font-size: 13px; + margin: 2px 0; + padding: 2px 5px; + color: #8A9094; + line-height: 1.25; + color: $sample-panel-headers-color; + + &.active { + background-color: white; + color: #666; + } +} + +:host tabs ul { + padding-top: 10px; +} + +pre { + overflow-x: auto; + word-break: break-all; + word-wrap: break-word; + white-space: pre-wrap; +} diff --git a/lib/components/SchemaSample/schema-sample.js b/lib/components/SchemaSample/schema-sample.js index 79382e53..43a014a7 100644 --- a/lib/components/SchemaSample/schema-sample.js +++ b/lib/components/SchemaSample/schema-sample.js @@ -22,11 +22,6 @@ export default class SchemaSample extends BaseComponent { init() { this.data = {}; - // sometimes for some reason this method is called without resolved pointer - // TODO: fix it and remove the following workaround - if (!this.componentSchema || !this.pointer) { - return; - } let base = {}; let sample; diff --git a/lib/components/SideMenu/side-menu.spec.js b/lib/components/SideMenu/side-menu.spec.js index 975f4b46..8b3da94f 100644 --- a/lib/components/SideMenu/side-menu.spec.js +++ b/lib/components/SideMenu/side-menu.spec.js @@ -36,7 +36,7 @@ describe('Redoc components', () => { ]); beforeEach(injectAsync([TestComponentBuilder, SchemaManager], (tcb, schemaMgr) => { builder = tcb; - return schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => null, (err) => { throw err; }); + return schemaMgr.load('/tests/schemas/extended-petstore.yml').then(() => null, (err) => { throw err; }); })); afterEach(() => { diff --git a/lib/utils/pipes.js b/lib/utils/pipes.js index 664f70c7..df4bd4e2 100644 --- a/lib/utils/pipes.js +++ b/lib/utils/pipes.js @@ -5,6 +5,29 @@ import {isString, stringify, isBlank} from 'angular2/src/facade/lang'; import {BaseException} from 'angular2/src/facade/exceptions'; import {JsonPointer} from './JsonPointer'; import marked from 'marked'; +import Prism from 'prismjs'; +import 'prismjs/components/prism-actionscript.js'; +import 'prismjs/components/prism-c.js'; +import 'prismjs/components/prism-cpp.js'; +import 'prismjs/components/prism-csharp.js'; +import 'prismjs/components/prism-php.js'; +import 'prismjs/components/prism-coffeescript.js'; +import 'prismjs/components/prism-go.js'; +import 'prismjs/components/prism-haskell.js'; +//import 'prismjs/components/prism-scala.js'; +import 'prismjs/components/prism-java.js'; +import 'prismjs/components/prism-lua.js'; +import 'prismjs/components/prism-matlab.js'; +import 'prismjs/components/prism-objectivec.js'; +import 'prismjs/components/prism-perl.js'; +import 'prismjs/components/prism-python.js'; +import 'prismjs/components/prism-r.js'; +import 'prismjs/components/prism-ruby.js'; +import 'prismjs/components/prism-bash.js'; +import 'prismjs/components/prism-swift.js'; +import 'prismjs/components/prism-vim.js'; + +import 'prismjs/themes/prism-dark.css!css'; marked.setOptions({ renderer: new marked.Renderer(), @@ -65,3 +88,31 @@ export class MarkedPipe { return `${marked(value)}`; } } + +const langMap = { + 'c++': 'cpp', + 'c#': 'csharp', + 'objective-c': 'objectivec', + 'shell': 'bash', + 'viml': 'vim' +}; + +@Pipe({ name: 'prism' }) +export class PrismPipe { + transform(value, args) { + if (isBlank(args) || args.length === 0) { + throw new BaseException('Prism pipe requires one argument'); + } + if (isBlank(value)) return value; + if (!isString(value)) { + throw new InvalidPipeArgumentException(JsonPointerEscapePipe, value); + } + let lang = args[0].toString().trim().toLowerCase(); + if (langMap[lang]) lang = langMap[lang]; + + let grammar = Prism.languages[lang]; + //fallback to clike + if (!grammar) grammar = Prism.languages.clike; + return Prism.highlight(value, grammar); + } +} diff --git a/package.json b/package.json index 08931192..458fb67b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redoc", "description": "Swagger-generated API Reference Documentation", - "version": "0.4.0", + "version": "0.5.0", "repository": { "type": "git", "url": "git://github.com/Rebilly/ReDoc" @@ -36,6 +36,7 @@ "json-schema-instantiator": "npm:json-schema-instantiator@^0.3.0", "json-schema-ref-parser": "npm:json-schema-ref-parser@2.2.0", "marked": "npm:marked@^0.3.5", + "prismjs": "npm:prismjs@^1.3.0", "scrollparent": "npm:scrollparent@^0.1.0", "swagger-parser": "npm:swagger-parser@^3.4.0" }, diff --git a/system.config.js b/system.config.js index c2663cd8..b3f9a4ff 100644 --- a/system.config.js +++ b/system.config.js @@ -50,6 +50,7 @@ System.config({ "json-schema-instantiator": "npm:json-schema-instantiator@0.3.0", "json-schema-ref-parser": "npm:json-schema-ref-parser@2.2.0", "marked": "npm:marked@0.3.5", + "prismjs": "npm:prismjs@1.3.0", "scrollparent": "npm:scrollparent@0.1.0", "swagger-parser": "npm:swagger-parser@3.4.0", "systemjs/plugin-json": "github:systemjs/plugin-json@0.1.0", @@ -538,25 +539,6 @@ System.config({ "npm:json-pointer@0.3.0": { "foreach": "npm:foreach@2.0.5" }, - "npm:json-schema-ref-parser@1.4.1": { - "buffer": "github:jspm/nodelibs-buffer@0.1.0", - "call-me-maybe": "npm:call-me-maybe@1.0.1", - "debug": "npm:debug@2.2.0", - "es6-promise": "npm:es6-promise@3.0.2", - "events": "github:jspm/nodelibs-events@0.1.1", - "fs": "github:jspm/nodelibs-fs@0.1.2", - "http": "github:jspm/nodelibs-http@1.7.1", - "https": "github:jspm/nodelibs-https@0.1.0", - "js-yaml": "npm:js-yaml@3.5.2", - "ono": "npm:ono@2.0.1", - "process": "github:jspm/nodelibs-process@0.1.2", - "punycode": "github:jspm/nodelibs-punycode@0.1.0", - "querystring": "github:jspm/nodelibs-querystring@0.1.0", - "stream": "github:jspm/nodelibs-stream@0.1.0", - "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0", - "url": "github:jspm/nodelibs-url@0.1.0", - "util": "github:jspm/nodelibs-util@0.1.0" - }, "npm:json-schema-ref-parser@2.2.0": { "buffer": "github:jspm/nodelibs-buffer@0.1.0", "call-me-maybe": "npm:call-me-maybe@1.0.1", @@ -660,6 +642,11 @@ System.config({ "npm:pinkie@2.0.1": { "process": "github:jspm/nodelibs-process@0.1.2" }, + "npm:prismjs@1.3.0": { + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "fs": "github:jspm/nodelibs-fs@0.1.2", + "process": "github:jspm/nodelibs-process@0.1.2" + }, "npm:process-nextick-args@1.0.6": { "process": "github:jspm/nodelibs-process@0.1.2" }, diff --git a/tests/schemas/extended-petstore.json b/tests/schemas/extended-petstore.json deleted file mode 100644 index d734204f..00000000 --- a/tests/schemas/extended-petstore.json +++ /dev/null @@ -1,869 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.", - "version": "1.0.0", - "title": "Swagger Petstore", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "email": "apiteam@swagger.io" - }, - "x-logo": { - "url": "https://rebilly.github.io/ReDoc/petstore-logo.png" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - } - }, - "host": "petstore.swagger.io", - "basePath": "/v2/", - "tags": [{ - "name": "Pagination", - "x-traitTag": true, - "description": "Sometimes you just can't get enough. For this reason, we've provided a convenient way to access more data in any request for sequential data. Simply call the url in the next_url parameter and we'll respond with the next set of data.\n```json\n{\n ...\n \"pagination\": {\n \"next_url\": \"https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296\",\n \"next_max_id\": \"13872296\"\n }\n}\n```\n On views where pagination is present, we also support the `count` parameter. Simply set this to the number of items you'd like to receive. Note that the default values should be fine for most applications - but if you decide to increase this number there is a maximum value defined on each endpoint.", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - },{ - "name": "JSONP", - "x-traitTag": true, - "description": "If you're writing an AJAX application, and you'd like to wrap our response with a callback, all you have to do is specify a callback parameter with any API call:\n```\n https://api.instagram.com/v1/tags/coffee/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&callback=callbackFunction\n```\nWould respond with:\n```js\ncallbackFunction({\n ...\n});\n```", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - },{ - "name": "pet", - "description": "Everything about your Pets", - "externalDocs": { - "description": "Find out more", - "url": "http://swagger.io" - } - }, { - "name": "store", - "description": "Access to Petstore orders" - }, { - "name": "user", - "description": "Operations about user", - "externalDocs": { - "description": "Find out more about our store", - "url": "http://swagger.io" - } - }], - "schemes": ["http"], - "paths": { - "/pet": { - "post": { - "tags": ["pet"], - "summary": "Add a new pet to the store", - "description": "", - "operationId": "addPet", - "consumes": ["application/json", "application/xml"], - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "Pet object that needs to be added to the store", - "required": true, - "schema": { - "$ref": "#/definitions/Pet" - } - }], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - }, - "put": { - "tags": ["pet"], - "summary": "Update an existing pet", - "description": "", - "operationId": "updatePet", - "consumes": ["application/json", "application/xml"], - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "Pet object that needs to be added to the store", - "required": true, - "schema": { - "$ref": "#/definitions/Pet" - } - }], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - }, - "405": { - "description": "Validation exception" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/findByStatus": { - "get": { - "tags": ["pet", "Pagination", "JSONP"], - "summary": "Finds Pets by status", - "description": "Multiple status values can be provided with comma seperated strings", - "operationId": "findPetsByStatus", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "status", - "in": "query", - "description": "Status values that need to be considered for filter", - "required": true, - "type": "array", - "items": { - "type": "string", - "enum": ["available", "pending", "sold"], - "default": "available" - }, - "collectionFormat": "csv" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Pet" - } - } - }, - "400": { - "description": "Invalid status value" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/findByTags": { - "get": { - "tags": ["pet", "Pagination", "JSONP"], - "summary": "Finds Pets by tags", - "description": "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", - "operationId": "findPetsByTags", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "tags", - "in": "query", - "description": "Tags to filter by", - "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/Pet" - } - } - }, - "400": { - "description": "Invalid tag value" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/{petId}": { - "get": { - "tags": ["pet", "JSONP"], - "summary": "Find pet by ID", - "description": "Returns a single pet", - "operationId": "getPetById", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "petId", - "in": "path", - "description": "ID of pet to return", - "required": true, - "type": "integer", - "format": "int64" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Pet" - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Pet not found" - } - }, - "security": [{ - "api_key": [] - }] - }, - "post": { - "tags": ["pet"], - "summary": "Updates a pet in the store with form data", - "description": "", - "operationId": "updatePetWithForm", - "consumes": ["application/x-www-form-urlencoded"], - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "petId", - "in": "path", - "description": "ID of pet that needs to be updated", - "required": true, - "type": "integer", - "format": "int64" - }, { - "name": "name", - "in": "formData", - "description": "Updated name of the pet", - "required": false, - "type": "string" - }, { - "name": "status", - "in": "formData", - "description": "Updated status of the pet", - "required": false, - "type": "string" - }], - "responses": { - "405": { - "description": "Invalid input" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - }, - "delete": { - "tags": ["pet"], - "summary": "Deletes a pet", - "description": "", - "operationId": "deletePet", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "api_key", - "in": "header", - "required": false, - "type": "string" - }, { - "name": "petId", - "in": "path", - "description": "Pet id to delete", - "required": true, - "type": "integer", - "format": "int64" - }], - "responses": { - "400": { - "description": "Invalid pet value" - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/pet/{petId}/uploadImage": { - "post": { - "tags": ["pet"], - "summary": "uploads an image", - "description": "", - "operationId": "uploadFile", - "consumes": ["multipart/form-data"], - "produces": ["application/json"], - "parameters": [{ - "name": "petId", - "in": "path", - "description": "ID of pet to update", - "required": true, - "type": "integer", - "format": "int64" - }, { - "name": "additionalMetadata", - "in": "formData", - "description": "Additional data to pass to server", - "required": false, - "type": "string" - }, { - "name": "file", - "in": "formData", - "description": "file to upload", - "required": false, - "type": "file" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/ApiResponse" - } - } - }, - "security": [{ - "petstore_auth": ["write:pets", "read:pets"] - }] - } - }, - "/store/inventory": { - "get": { - "tags": ["store", "JSONP"], - "summary": "Returns pet inventories by status", - "description": "Returns a map of status codes to quantities", - "operationId": "getInventory", - "produces": ["application/json"], - "parameters": [], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int32" - } - } - } - }, - "security": [{ - "api_key": [] - }] - } - }, - "/store/order": { - "post": { - "tags": ["store"], - "summary": "Place an order for a pet", - "description": "", - "operationId": "placeOrder", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "order placed for purchasing the pet", - "required": true, - "schema": { - "$ref": "#/definitions/Order" - } - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Order" - } - }, - "400": { - "description": "Invalid Order" - } - } - } - }, - "/store/order/{orderId}": { - "get": { - "tags": ["store", "JSONP"], - "summary": "Find purchase order by ID", - "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", - "operationId": "getOrderById", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "orderId", - "in": "path", - "description": "ID of pet that needs to be fetched", - "required": true, - "type": "integer", - "maximum": 5.0, - "minimum": 1.0, - "format": "int64" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/Order" - } - }, - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - }, - "delete": { - "tags": ["store"], - "summary": "Delete purchase order by ID", - "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", - "operationId": "deleteOrder", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "orderId", - "in": "path", - "description": "ID of the order that needs to be deleted", - "required": true, - "type": "string", - "minimum": 1.0 - }], - "responses": { - "400": { - "description": "Invalid ID supplied" - }, - "404": { - "description": "Order not found" - } - } - } - }, - "/user": { - "post": { - "tags": ["user"], - "summary": "Create user", - "description": "This can only be done by the logged in user.", - "operationId": "createUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "Created user object", - "required": true, - "schema": { - "$ref": "#/definitions/User" - } - }], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/createWithArray": { - "post": { - "tags": ["user"], - "summary": "Creates list of users with given input array", - "description": "", - "operationId": "createUsersWithArrayInput", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "List of user object", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/User" - } - } - }], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/createWithList": { - "post": { - "tags": ["user"], - "summary": "Creates list of users with given input array", - "description": "", - "operationId": "createUsersWithListInput", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "in": "body", - "name": "body", - "description": "List of user object", - "required": true, - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/User" - } - } - }], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/login": { - "get": { - "tags": ["user"], - "summary": "Logs user into the system", - "description": "", - "operationId": "loginUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "query", - "description": "The user name for login", - "required": true, - "type": "string" - }, { - "name": "password", - "in": "query", - "description": "The password for login in clear text", - "required": true, - "type": "string" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "type": "string" - }, - "headers": { - "X-Rate-Limit": { - "type": "integer", - "format": "int32", - "description": "calls per hour allowed by the user" - }, - "X-Expires-After": { - "type": "string", - "format": "date-time", - "description": "date in UTC when toekn expires" - } - } - }, - "400": { - "description": "Invalid username/password supplied" - } - } - } - }, - "/user/logout": { - "get": { - "tags": ["user"], - "summary": "Logs out current logged in user session", - "description": "", - "operationId": "logoutUser", - "produces": ["application/xml", "application/json"], - "parameters": [], - "responses": { - "default": { - "description": "successful operation" - } - } - } - }, - "/user/{username}": { - "get": { - "tags": ["user", "JSONP"], - "summary": "Get user by user name", - "description": "", - "operationId": "getUserByName", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "path", - "description": "The name that needs to be fetched. Use user1 for testing. ", - "required": true, - "type": "string" - }], - "responses": { - "200": { - "description": "successful operation", - "schema": { - "$ref": "#/definitions/User" - } - }, - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "put": { - "tags": ["user"], - "summary": "Updated user", - "description": "This can only be done by the logged in user.", - "operationId": "updateUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "path", - "description": "name that need to be deleted", - "required": true, - "type": "string" - }, { - "in": "body", - "name": "body", - "description": "Updated user object", - "required": true, - "schema": { - "$ref": "#/definitions/User" - } - }], - "responses": { - "400": { - "description": "Invalid user supplied" - }, - "404": { - "description": "User not found" - } - } - }, - "delete": { - "tags": ["user"], - "summary": "Delete user", - "description": "This can only be done by the logged in user.", - "operationId": "deleteUser", - "produces": ["application/xml", "application/json"], - "parameters": [{ - "name": "username", - "in": "path", - "description": "The name that needs to be deleted", - "required": true, - "type": "string" - }], - "responses": { - "400": { - "description": "Invalid username supplied" - }, - "404": { - "description": "User not found" - } - } - } - } - }, - "securityDefinitions": { - "petstore_auth": { - "type": "oauth2", - "authorizationUrl": "http://petstore.swagger.io/api/oauth/dialog", - "flow": "implicit", - "scopes": { - "write:pets": "modify pets in your account", - "read:pets": "read your pets" - } - }, - "api_key": { - "type": "apiKey", - "name": "api_key", - "in": "header" - } - }, - "definitions": { - "Order": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "petId": { - "type": "integer", - "format": "int64" - }, - "quantity": { - "type": "integer", - "format": "int32" - }, - "shipDate": { - "type": "string", - "format": "date-time" - }, - "status": { - "type": "string", - "description": "Order Status", - "enum": ["placed", "approved", "delivered"] - }, - "complete": { - "type": "boolean", - "default": false - } - }, - "xml": { - "name": "Order" - } - }, - "User": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "username": { - "type": "string" - }, - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - }, - "email": { - "type": "string" - }, - "password": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "userStatus": { - "type": "integer", - "format": "int32", - "description": "User Status" - } - }, - "xml": { - "name": "User" - } - }, - "Category": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "Category" - } - }, - "Tag": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - }, - "xml": { - "name": "Tag" - } - }, - "Pet": { - "type": "object", - "required": ["name", "photoUrls", "petType"], - "discriminator": "petType", - "properties": { - "petType": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "category": { - "$ref": "#/definitions/Category" - }, - "name": { - "type": "string", - "example": "doggie" - }, - "photoUrls": { - "type": "array", - "xml": { - "name": "photoUrl", - "wrapped": true - }, - "items": { - "type": "string" - } - }, - "tags": { - "type": "array", - "xml": { - "name": "tag", - "wrapped": true - }, - "items": { - "$ref": "#/definitions/Tag" - } - }, - "status": { - "type": "string", - "description": "pet status in the store", - "enum": ["available", "pending", "sold"] - } - }, - "xml": { - "name": "Pet" - } - }, - "Cat": { - "description": "A representation of a cat", - "allOf": [ - { - "type": "object", - "properties": { - "huntingSkill": { - "type": "string", - "description": "The measured skill for hunting", - "default": "lazy", - "enum": [ - "clueless", - "lazy", - "adventurous", - "aggressive" - ] - } - }, - "required": [ - "huntingSkill" - ] - }, - { - "$ref": "#/definitions/Pet" - }, - ] - }, - "ApiResponse": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32" - }, - "type": { - "type": "string" - }, - "message": { - "type": "string" - } - } - } - }, - "externalDocs": { - "description": "Find out more about Swagger", - "url": "http://swagger.io" - } -} diff --git a/tests/schemas/extended-petstore.yml b/tests/schemas/extended-petstore.yml new file mode 100644 index 00000000..0a41c2ee --- /dev/null +++ b/tests/schemas/extended-petstore.yml @@ -0,0 +1,862 @@ +--- + swagger: "2.0" + info: + description: "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters." + version: "1.0.0" + title: "Swagger Petstore" + termsOfService: "http://swagger.io/terms/" + contact: + email: "apiteam@swagger.io" + x-logo: + url: "https://rebilly.github.io/ReDoc/petstore-logo.png" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" + host: "petstore.swagger.io" + basePath: "/v2" + tags: + - + name: "Pagination" + x-traitTag: true + description: |- + Sometimes you just can't get enough. For this reason, we've provided a convenient way to access more data in + any request for sequential data. Simply call the url in the next_url parameter and we'll respond with the next + set of data. + + ```json + { + ... + "pagination": { + "next_url": "https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296", + "next_max_id": "13872296" + } + } + ``` + + On views where pagination is present, we also support the `count` parameter. + Simply set this to the number of items you'd like to receive. Note that the default values + should be fine for most applications - but if you decide to increase this number there is a maximum value + defined on each endpoint. + externalDocs: + description: "Find out more" + url: "http://swagger.io" + - + name: "JSONP" + x-traitTag: true + description: |- + If you're writing an AJAX application, and you'd like to wrap our response with a callback, + all you have to do is specify a callback parameter with any API call: + + ``` + https://api.instagram.com/v1/tags/coffee/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&callback=callbackFunction + ``` + Would respond with: + + ```js + callbackFunction({ + ... + }); + ``` + + > Example of markdown blockquote + externalDocs: + description: "Find out more" + url: "http://swagger.io" + - + name: "pet" + description: "Everything about your Pets" + externalDocs: + description: "Find out more" + url: "http://swagger.io" + - + name: "store" + description: "Access to Petstore orders" + - + name: "user" + description: "Operations about user" + externalDocs: + description: "Find out more about our store" + url: "http://swagger.io" + schemes: + - "http" + paths: + /pet: + post: + tags: + - "pet" + summary: "Add a new pet to the store" + description: "" + operationId: "addPet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 405: + description: "Invalid input" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + x-code-samples: + - + lang: PHP + source: |- + $form = new \PetStore\Entities\Pet(); + $form->setPetType("Dog"); + $form->setName("Rex"); + // set other fields + + try { + $pet = $client->pets()->create($form); + } catch (UnprocessableEntityException $e) { + var_dump($e->getErrors()); + } + - + lang: C# + source: |- + PetStore.v1.Pet pet = new PetStore.v1.Pet(); + pet.setApiKey("your api key"); + pet.petType = PetStore.v1.Pet.TYPE_DOG; + pet.name = "Rex"; + // set other fields + + PetStoreResponse response = pet.create(); + if (response.statusCode == HttpStatusCode.Created) + { + // Successfully created + } + else + { + // Something wrong -- check response for errors + Console.WriteLine(response.getRawResponse()); + } + put: + tags: + - "pet" + summary: "Update an existing pet" + description: "" + operationId: "updatePet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + 405: + description: "Validation exception" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByStatus: + get: + tags: + - "pet" + - "Pagination" + - "JSONP" + summary: "Finds Pets by status" + description: "Multiple status values can be provided with comma seperated strings" + operationId: "findPetsByStatus" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "status" + in: "query" + description: "Status values that need to be considered for filter" + required: true + type: "array" + items: + type: "string" + enum: + - "available" + - "pending" + - "sold" + default: "available" + collectionFormat: "csv" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid status value" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByTags: + get: + tags: + - "pet" + - "Pagination" + - "JSONP" + summary: "Finds Pets by tags" + description: "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing." + operationId: "findPetsByTags" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "tags" + in: "query" + description: "Tags to filter by" + required: true + type: "array" + items: + type: "string" + collectionFormat: "csv" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid tag value" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/{petId}: + get: + tags: + - "pet" + - "JSONP" + summary: "Find pet by ID" + description: "Returns a single pet" + operationId: "getPetById" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "petId" + in: "path" + description: "ID of pet to return" + required: true + type: "integer" + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Pet" + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + security: + - + api_key: [] + post: + tags: + - "pet" + summary: "Updates a pet in the store with form data" + description: "" + operationId: "updatePetWithForm" + consumes: + - "application/x-www-form-urlencoded" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "petId" + in: "path" + description: "ID of pet that needs to be updated" + required: true + type: "integer" + format: "int64" + - + name: "name" + in: "formData" + description: "Updated name of the pet" + required: false + type: "string" + - + name: "status" + in: "formData" + description: "Updated status of the pet" + required: false + type: "string" + responses: + 405: + description: "Invalid input" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + delete: + tags: + - "pet" + summary: "Deletes a pet" + description: "" + operationId: "deletePet" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "api_key" + in: "header" + required: false + type: "string" + - + name: "petId" + in: "path" + description: "Pet id to delete" + required: true + type: "integer" + format: "int64" + responses: + 400: + description: "Invalid pet value" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /pet/{petId}/uploadImage: + post: + tags: + - "pet" + summary: "uploads an image" + description: "" + operationId: "uploadFile" + consumes: + - "multipart/form-data" + produces: + - "application/json" + parameters: + - + name: "petId" + in: "path" + description: "ID of pet to update" + required: true + type: "integer" + format: "int64" + - + name: "additionalMetadata" + in: "formData" + description: "Additional data to pass to server" + required: false + type: "string" + - + name: "file" + in: "formData" + description: "file to upload" + required: false + type: "file" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + security: + - + petstore_auth: + - "write:pets" + - "read:pets" + /store/inventory: + get: + tags: + - "store" + - "JSONP" + summary: "Returns pet inventories by status" + description: "Returns a map of status codes to quantities" + operationId: "getInventory" + produces: + - "application/json" + parameters: [] + responses: + 200: + description: "successful operation" + schema: + type: "object" + additionalProperties: + type: "integer" + format: "int32" + security: + - + api_key: [] + /store/order: + post: + tags: + - "store" + summary: "Place an order for a pet" + description: "" + operationId: "placeOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "order placed for purchasing the pet" + required: true + schema: + $ref: "#/definitions/Order" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid Order" + /store/order/{orderId}: + get: + tags: + - "store" + - "JSONP" + summary: "Find purchase order by ID" + description: "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions" + operationId: "getOrderById" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "orderId" + in: "path" + description: "ID of pet that needs to be fetched" + required: true + type: "integer" + maximum: 5 + minimum: 1 + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + delete: + tags: + - "store" + summary: "Delete purchase order by ID" + description: "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors" + operationId: "deleteOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "orderId" + in: "path" + description: "ID of the order that needs to be deleted" + required: true + type: "string" + minimum: 1 + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + /user: + post: + tags: + - "user" + summary: "Create user" + description: "This can only be done by the logged in user." + operationId: "createUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "Created user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithArray: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithArrayInput" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithList: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithListInput" + produces: + - "application/xml" + - "application/json" + parameters: + - + in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/login: + get: + tags: + - "user" + summary: "Logs user into the system" + description: "" + operationId: "loginUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "query" + description: "The user name for login" + required: true + type: "string" + - + name: "password" + in: "query" + description: "The password for login in clear text" + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + type: "string" + headers: + X-Rate-Limit: + type: "integer" + format: "int32" + description: "calls per hour allowed by the user" + X-Expires-After: + type: "string" + format: "date-time" + description: "date in UTC when toekn expires" + 400: + description: "Invalid username/password supplied" + /user/logout: + get: + tags: + - "user" + summary: "Logs out current logged in user session" + description: "" + operationId: "logoutUser" + produces: + - "application/xml" + - "application/json" + parameters: [] + responses: + default: + description: "successful operation" + /user/{username}: + get: + tags: + - "user" + - "JSONP" + summary: "Get user by user name" + description: "" + operationId: "getUserByName" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "path" + description: "The name that needs to be fetched. Use user1 for testing. " + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/User" + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + put: + tags: + - "user" + summary: "Updated user" + description: "This can only be done by the logged in user." + operationId: "updateUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "path" + description: "name that need to be deleted" + required: true + type: "string" + - + in: "body" + name: "body" + description: "Updated user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + 400: + description: "Invalid user supplied" + 404: + description: "User not found" + delete: + tags: + - "user" + summary: "Delete user" + description: "This can only be done by the logged in user." + operationId: "deleteUser" + produces: + - "application/xml" + - "application/json" + parameters: + - + name: "username" + in: "path" + description: "The name that needs to be deleted" + required: true + type: "string" + responses: + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + securityDefinitions: + petstore_auth: + type: "oauth2" + authorizationUrl: "http://petstore.swagger.io/api/oauth/dialog" + flow: "implicit" + scopes: + write:pets: "modify pets in your account" + read:pets: "read your pets" + api_key: + type: "apiKey" + name: "api_key" + in: "header" + definitions: + Order: + type: "object" + properties: + id: + type: "integer" + format: "int64" + petId: + type: "integer" + format: "int64" + quantity: + type: "integer" + format: "int32" + shipDate: + type: "string" + format: "date-time" + status: + type: "string" + description: "Order Status" + enum: + - "placed" + - "approved" + - "delivered" + complete: + type: "boolean" + default: false + xml: + name: "Order" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + username: + type: "string" + firstName: + type: "string" + lastName: + type: "string" + email: + type: "string" + password: + type: "string" + phone: + type: "string" + userStatus: + type: "integer" + format: "int32" + description: "User Status" + xml: + name: "User" + Category: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Category" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Tag" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + - "petType" + discriminator: "petType" + properties: + petType: + type: "string" + id: + type: "integer" + format: "int64" + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + xml: + name: "Pet" + Cat: + description: "A representation of a cat" + allOf: + - + $ref: "#/definitions/Pet" + - + type: "object" + properties: + huntingSkill: + type: "string" + description: "The measured skill for hunting" + default: "lazy" + enum: + - "clueless" + - "lazy" + - "adventurous" + - "aggressive" + required: + - "huntingSkill" + Dog: + description: "A representation of a dog" + allOf: + - + $ref: "#/definitions/Pet" + - + type: "object" + properties: + packSize: + type: "integer" + format: "int32" + description: "the size of the pack the dog is from" + default: 0 + minimum: 0 + required: + - "packSize" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" + externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io" diff --git a/tests/unit/SchemaManager.spec.js b/tests/unit/SchemaManager.spec.js index 3df2b985..0a2bfbf8 100644 --- a/tests/unit/SchemaManager.spec.js +++ b/tests/unit/SchemaManager.spec.js @@ -19,7 +19,7 @@ describe('Utils', () => { }); it('load should return a promise', ()=> { - schemaMgr.load('/tests/schemas/extended-petstore.json').should.be.instanceof(Promise); + schemaMgr.load('/tests/schemas/extended-petstore.yml').should.be.instanceof(Promise); }); it('load should reject promise for invalid url', (done)=> { @@ -31,7 +31,7 @@ describe('Utils', () => { }); it('load should resolve promise for valid url', (done)=> { - schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => { + schemaMgr.load('/tests/schemas/extended-petstore.yml').then(() => { done(); }, () => { throw new Error('Error handler should not be called'); @@ -40,7 +40,7 @@ describe('Utils', () => { describe('Schema manager basic functionality', ()=> { beforeAll(function (done) { - schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => { + schemaMgr.load('/tests/schemas/extended-petstore.yml').then(() => { done(); }, () => { throw new Error('Error handler should not be called'); @@ -227,7 +227,7 @@ describe('Utils', () => { describe('findDerivedDefinitions method', () => { beforeAll((done) => { - schemaMgr.load('/tests/schemas/extended-petstore.json').then(() => { + schemaMgr.load('/tests/schemas/extended-petstore.yml').then(() => { done(); }, () => { done(new Error('Error handler should not be called')); @@ -237,8 +237,8 @@ describe('Utils', () => { it('should find derived definitions for Pet', () => { let deriveDefs = schemaMgr.findDerivedDefinitions('#/definitions/Pet'); deriveDefs.should.be.instanceof(Array); - deriveDefs.should.not.be.empty; - deriveDefs.should.be.deepEqual([{name: 'Cat', $ref: '#/definitions/Cat'}]); + deriveDefs.should.not.be.empty(); + deriveDefs.should.be.deepEqual([{name: 'Cat', $ref: '#/definitions/Cat'}, {name: 'Dog', $ref: '#/definitions/Dog'}]); }); it('should return emtpy array for definitions that dont have discriminator', () => {