@@ -22,7 +22,7 @@ The OpenAPI Specification has undergone 5 revisions since initial creation in 20 | |||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | |||
------------------ | ------------ | -------------------------- | ----- | |||
3.1.2 | 2017-07-31 | 2.0, 3.0 | [tag v3.1.2](https://github.com/swagger-api/swagger-ui/tree/v3.1.2) | |||
3.1.3 | 2017-08-04 | 2.0, 3.0 | [tag v3.1.3](https://github.com/swagger-api/swagger-ui/tree/v3.1.3) | |||
3.0.21 | 2017-07-26 | 2.0 | [tag v3.0.21](https://github.com/swagger-api/swagger-ui/tree/v3.0.21) | |||
2.2.10 | 2017-01-04 | 1.1, 1.2, 2.0 | [tag v2.2.10](https://github.com/swagger-api/swagger-ui/tree/v2.2.10) | |||
2.1.5 | 2016-07-20 | 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-ui/tree/v2.1.5) | |||
@@ -104,7 +104,7 @@ To use swagger-ui's bundles, you should take a look at the [source of swagger-ui | |||
#### OAuth2 configuration | |||
You can configure OAuth2 authorization by calling `initOAuth` method with passed configs under the instance of `SwaggerUIBundle` | |||
default `client_id` and `client_secret`, `realm`, an application name `appName`, `scopeSeparator`, `additionalQueryStringParams`, | |||
default `client_id` and `client_secret`, `realm`, an application name `appName`, `scopeSeparator`, `additionalQueryStringParams`, | |||
`useBasicAuthenticationWithAccessCodeGrant`. | |||
Config Name | Description | |||
@@ -115,7 +115,7 @@ realm | realm query parameter (for oauth1) added to `authorizationUrl` and `toke | |||
appName | application name, displayed in authorization popup. MUST be a string | |||
scopeSeparator | scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string | |||
additionalQueryStringParams | Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object | |||
useBasicAuthenticationWithAccessCodeGrant | Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encoded[client_id:client_secret]`). The default is `false` | |||
useBasicAuthenticationWithAccessCodeGrant | Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encoded[client_id:client_secret]`). The default is `false` | |||
``` | |||
const ui = SwaggerUIBundle({...}) | |||
@@ -145,6 +145,7 @@ urls.primaryName | When using `urls`, you can use this subparameter. If the valu | |||
spec | A JSON object describing the OpenAPI Specification. When used, the `url` parameter will not be parsed. This is useful for testing manually-generated specifications without hosting them. | |||
validatorUrl | By default, Swagger-UI attempts to validate specs against swagger.io's online validator. You can use this parameter to set a different validator URL, for example for locally deployed validators ([Validator Badge](https://github.com/swagger-api/validator-badge)). Setting it to `null` will disable validation. | |||
dom_id | The id of a dom element inside which SwaggerUi will put the user interface for swagger. | |||
domNode | The HTML DOM element inside which SwaggerUi will put the user interface for swagger. Overrides `dom_id`. | |||
oauth2RedirectUrl | OAuth redirect URL | |||
tagsSorter | Apply a sort to the tag list of each API. It can be 'alpha' (sort by paths alphanumerically) or a function (see [Array.prototype.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) to learn how to write a sort function). Two tag name strings are passed to the sorter for each pass. Default is the order determined by Swagger-UI. | |||
operationsSorter | Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method) or a function (see Array.prototype.sort() to know how sort function works). Default is the order returned by the server unchanged. | |||
@@ -21,7 +21,6 @@ | |||
{ | |||
box-sizing: inherit; | |||
} | |||
body { | |||
margin:0; | |||
background: #fafafa; | |||
@@ -11,15 +11,15 @@ | |||
<style> | |||
html | |||
{ | |||
box-sizing: border-box; | |||
overflow: -moz-scrollbars-vertical; | |||
overflow-y: scroll; | |||
box-sizing: border-box; | |||
overflow: -moz-scrollbars-vertical; | |||
overflow-y: scroll; | |||
} | |||
*, | |||
*:before, | |||
*:after | |||
{ | |||
box-sizing: inherit; | |||
box-sizing: inherit; | |||
} | |||
body { | |||
@@ -1 +1 @@ | |||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;AAoyKA;;;;;;AAy+EA;;;;;;;;;;;;;;;;;;;;;;;;;;AA00TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AA+5oBA;;;;;AA2lQA;AAm4DA;;;;;;AAo4YA;;;;;;AA0iaA;AAumvBA","sourceRoot":""} | |||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;AAoyKA;;;;;;AAy+EA;;;;;;;;;;;;;;;;;;;;;;;;;;AAw1TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AAw6oBA;;;;;AAgrQA;AAm4DA;;;;;;AAo4YA;;;;;;AA8jaA;AAumvBA","sourceRoot":""} |
@@ -1 +1 @@ | |||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAwpcA","sourceRoot":""} | |||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAmwcA","sourceRoot":""} |
@@ -1,6 +1,6 @@ | |||
{ | |||
"name": "swagger-ui", | |||
"version": "3.1.2", | |||
"version": "3.1.3", | |||
"main": "dist/swagger-ui.js", | |||
"repository": "git@github.com:swagger-api/swagger-ui.git", | |||
"contributors": [ | |||
@@ -47,7 +47,6 @@ | |||
"ieee754": "^1.1.8", | |||
"immutable": "^3.x.x", | |||
"js-yaml": "^3.5.5", | |||
"less": "2.7.1", | |||
"lodash": "4.17.2", | |||
"matcher": "^0.1.2", | |||
"memoizee": "0.4.1", | |||
@@ -15,7 +15,7 @@ export default class ArrayModel extends Component { | |||
} | |||
render(){ | |||
let { getComponent, required, schema, depth, expandDepth, name } = this.props | |||
let { getComponent, schema, depth, expandDepth, name } = this.props | |||
let items = schema.get("items") | |||
let title = schema.get("title") || name | |||
let properties = schema.filter( ( v, key) => ["type", "items", "$$ref"].indexOf(key) === -1 ) | |||
@@ -31,7 +31,7 @@ export default class ArrayModel extends Component { | |||
return <span className="model"> | |||
<ModelCollapse title={titleEl} collapsed={ depth > expandDepth } collapsedContent="[...]"> | |||
[ | |||
<span><Model { ...this.props } schema={ items } required={ false }/></span> | |||
<span><Model { ...this.props } schema={ items } required={ false } depth={ depth + 1 } /></span> | |||
] | |||
{ | |||
properties.size ? <span> | |||
@@ -41,7 +41,6 @@ export default class ArrayModel extends Component { | |||
: null | |||
} | |||
</ModelCollapse> | |||
{ required && <span style={{ color: "red" }}>*</span>} | |||
</span> | |||
} | |||
} |
@@ -55,14 +55,14 @@ export default class Model extends Component { | |||
return <ObjectModel | |||
className="object" { ...this.props } | |||
schema={ modelSchema } | |||
name={ name || modelName } | |||
name={ modelName || name } | |||
deprecated={deprecated} | |||
isRef={ isRef!== undefined ? isRef : !!$$ref } /> | |||
case "array": | |||
return <ArrayModel | |||
className="array" { ...this.props } | |||
schema={ modelSchema } | |||
name={ name || modelName } | |||
name={ modelName || name } | |||
deprecated={deprecated} | |||
required={ required } /> | |||
case "string": | |||
@@ -74,8 +74,8 @@ export default class Model extends Component { | |||
{ ...this.props } | |||
getComponent={ getComponent } | |||
schema={ modelSchema } | |||
name={ name || modelName } | |||
name={ modelName || name } | |||
deprecated={deprecated} | |||
required={ required }/> } | |||
required={ required }/> } | |||
} | |||
} |
@@ -17,8 +17,9 @@ export default class ObjectModel extends Component { | |||
} | |||
render(){ | |||
let { schema, name, isRef, getComponent, depth, ...props } = this.props | |||
let { expandDepth } = this.props | |||
let { schema, name, isRef, getComponent, depth, expandDepth, specSelectors, ...props } = this.props | |||
let { isOAS3 } = specSelectors | |||
let description = schema.get("description") | |||
let properties = schema.get("properties") | |||
let additionalProperties = schema.get("additionalProperties") | |||
@@ -30,14 +31,21 @@ export default class ObjectModel extends Component { | |||
const Model = getComponent("Model") | |||
const ModelCollapse = getComponent("ModelCollapse") | |||
const JumpToPathSection = ({ name }) => <span className="model-jump-to-path"><JumpToPath path={`definitions.${name}`} /></span> | |||
const JumpToPathSection = ({ name }) => { | |||
const path = isOAS3 && isOAS3() ? `components.schemas.${name}` : `definitions.${name}` | |||
return <span className="model-jump-to-path"><JumpToPath path={path} /></span> | |||
} | |||
const collapsedContent = (<span> | |||
<span>{ braceOpen }</span>...<span>{ braceClose }</span> | |||
{ | |||
isRef ? <JumpToPathSection name={ name }/> : "" | |||
} | |||
</span>) | |||
const anyOf = specSelectors.isOAS3() ? schema.get("anyOf") : null | |||
const oneOf = specSelectors.isOAS3() ? schema.get("oneOf") : null | |||
const not = specSelectors.isOAS3() ? schema.get("not") : null | |||
const titleEl = title && <span className="model-title"> | |||
{ isRef && schema.get("$$ref") && <span className="model-hint">{ schema.get("$$ref") }</span> } | |||
<span className="model-title__text">{ title }</span> | |||
@@ -51,7 +59,7 @@ export default class ObjectModel extends Component { | |||
} | |||
<span className="inner-object"> | |||
{ | |||
<table className="model" style={{ marginLeft: "2em" }}><tbody> | |||
<table className="model"><tbody> | |||
{ | |||
!description ? null : <tr style={{ color: "#999", fontStyle: "italic" }}> | |||
<td>description:</td> | |||
@@ -95,6 +103,48 @@ export default class ObjectModel extends Component { | |||
</td> | |||
</tr> | |||
} | |||
{ | |||
!anyOf ? null | |||
: <tr> | |||
<td>{ "anyOf ->" }</td> | |||
<td> | |||
{anyOf.map((schema, k) => { | |||
return <div key={k}><Model { ...props } required={ false } | |||
getComponent={ getComponent } | |||
schema={ schema } | |||
depth={ depth + 1 } /></div> | |||
})} | |||
</td> | |||
</tr> | |||
} | |||
{ | |||
!oneOf ? null | |||
: <tr> | |||
<td>{ "oneOf ->" }</td> | |||
<td> | |||
{oneOf.map((schema, k) => { | |||
return <div key={k}><Model { ...props } required={ false } | |||
getComponent={ getComponent } | |||
schema={ schema } | |||
depth={ depth + 1 } /></div> | |||
})} | |||
</td> | |||
</tr> | |||
} | |||
{ | |||
!not ? null | |||
: <tr> | |||
<td>{ "not ->" }</td> | |||
<td> | |||
{not.map((schema, k) => { | |||
return <div key={k}><Model { ...props } required={ false } | |||
getComponent={ getComponent } | |||
schema={ schema } | |||
depth={ depth + 1 } /></div> | |||
})} | |||
</td> | |||
</tr> | |||
} | |||
</tbody></table> | |||
} | |||
</span> | |||
@@ -102,4 +152,4 @@ export default class ObjectModel extends Component { | |||
</ModelCollapse> | |||
</span> | |||
} | |||
} | |||
} |
@@ -186,7 +186,7 @@ export default class Operation extends PureComponent { | |||
} | |||
</div> | |||
<Collapse isOpened={shown} animated> | |||
<Collapse isOpened={shown}> | |||
<div className="opblock-body"> | |||
{ deprecated && <h4 className="opblock-title_normal"> Warning: Deprecated</h4>} | |||
{ description && | |||
@@ -58,6 +58,8 @@ export default class ParameterRow extends Component { | |||
render() { | |||
let {param, onChange, getComponent, isExecute, fn, onChangeConsumes, specSelectors, pathMethod} = this.props | |||
let { isOAS3 } = specSelectors | |||
// const onChangeWrapper = (value) => onChange(param, value) | |||
const JsonSchemaForm = getComponent("JsonSchemaForm") | |||
const ParamBody = getComponent("ParamBody") | |||
@@ -95,6 +97,9 @@ export default class ParameterRow extends Component { | |||
{ !required ? null : <span style={{color: "red"}}> *</span> } | |||
</div> | |||
<div className="parameter__type">{ param.get("type") } { itemType && `[${itemType}]` }</div> | |||
<div className="parameter__deprecated"> | |||
{ isOAS3 && isOAS3() && param.get("deprecated") ? "deprecated": null } | |||
</div> | |||
<div className="parameter__in">({ param.get("in") })</div> | |||
</td> | |||
@@ -7,11 +7,12 @@ export default class Primitive extends Component { | |||
static propTypes = { | |||
schema: PropTypes.object.isRequired, | |||
getComponent: PropTypes.func.isRequired, | |||
required: PropTypes.bool | |||
name: PropTypes.string, | |||
depth: PropTypes.number | |||
} | |||
render(){ | |||
let { schema, getComponent, required } = this.props | |||
let { schema, getComponent, name, depth } = this.props | |||
if(!schema || !schema.get) { | |||
// don't render if schema isn't correctly formed | |||
@@ -24,32 +25,34 @@ export default class Primitive extends Component { | |||
let enumArray = schema.get("enum") | |||
let description = schema.get("description") | |||
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 ) | |||
let style = required ? { fontWeight: "bold" } : {} | |||
const Markdown = getComponent("Markdown") | |||
const EnumModel = getComponent("EnumModel") | |||
return <span className="prop"> | |||
<span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>} | |||
{ format && <span className="prop-format">(${format})</span>} | |||
{ | |||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }> | |||
<br />{ key }: { String(v) }</span>) | |||
: null | |||
} | |||
{ | |||
!description ? null : | |||
<Markdown source={ description } /> | |||
} | |||
{ | |||
xml && xml.size ? (<span><br /><span style={ propStyle }>xml:</span> | |||
{ | |||
xml.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }><br/> {key}: { String(v) }</span>).toArray() | |||
} | |||
</span>): null | |||
} | |||
{ | |||
enumArray && <EnumModel value={ enumArray } getComponent={ getComponent } /> | |||
} | |||
return <span className="model"> | |||
<span className="prop"> | |||
{ name && <span className={`${depth === 1 && "model-title"} prop-name`}>{ name }</span> } | |||
<span className="prop-type">{ type }</span> | |||
{ format && <span className="prop-format">(${format})</span>} | |||
{ | |||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }> | |||
<br />{ key }: { String(v) }</span>) | |||
: null | |||
} | |||
{ | |||
!description ? null : | |||
<Markdown source={ description } /> | |||
} | |||
{ | |||
xml && xml.size ? (<span><br /><span style={ propStyle }>xml:</span> | |||
{ | |||
xml.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }><br/> {key}: { String(v) }</span>).toArray() | |||
} | |||
</span>): null | |||
} | |||
{ | |||
enumArray && <EnumModel value={ enumArray } getComponent={ getComponent } /> | |||
} | |||
</span> | |||
</span> | |||
} | |||
} |
@@ -23,6 +23,7 @@ module.exports = function SwaggerUI(opts) { | |||
const defaults = { | |||
// Some general settings, that we floated to the top | |||
dom_id: null, | |||
domNode: null, | |||
spec: {}, | |||
url: "", | |||
urls: null, | |||
@@ -99,6 +100,12 @@ module.exports = function SwaggerUI(opts) { | |||
let localConfig = system.specSelectors.getLocalConfig ? system.specSelectors.getLocalConfig() : {} | |||
let mergedConfig = deepExtend({}, localConfig, constructorConfig, fetchedConfig || {}, queryConfig) | |||
// deep extend mangles domNode, we need to set it manually | |||
if(opts.domNode) { | |||
mergedConfig.domNode = opts.domNode | |||
} | |||
store.setConfigs(mergedConfig) | |||
if (fetchedConfig !== null) { | |||
@@ -112,10 +119,13 @@ module.exports = function SwaggerUI(opts) { | |||
} | |||
} | |||
if(mergedConfig.dom_id) { | |||
system.render(mergedConfig.dom_id, "App") | |||
if(mergedConfig.domNode) { | |||
system.render(mergedConfig.domNode, "App") | |||
} else if(mergedConfig.dom_id) { | |||
let domNode = document.querySelector(mergedConfig.dom_id) | |||
system.render(domNode, "App") | |||
} else { | |||
console.error("Skipped rendering: no `dom_id` was specified") | |||
console.error("Skipped rendering: no `dom_id` or `domNode` was specified") | |||
} | |||
return system | |||
@@ -150,7 +150,6 @@ export const authorizeRequest = ( data ) => ( { fn, authActions, errActions, aut | |||
let _headers = Object.assign({ | |||
"Accept":"application/json, text/plain, */*", | |||
"Access-Control-Allow-Origin": "*", | |||
"Content-Type": "application/x-www-form-urlencoded" | |||
}, headers) | |||
@@ -3,7 +3,6 @@ import PropTypes from "prop-types" | |||
import { OAS3ComponentWrapFactory } from "../helpers" | |||
import { Model } from "core/components/model" | |||
class ModelComponent extends Component { | |||
static propTypes = { | |||
schema: PropTypes.object.isRequired, | |||
@@ -58,8 +58,7 @@ export const makeMappedContainer = (getSystem, getStore, memGetComponent, getCom | |||
} | |||
export const render = (getSystem, getStore, getComponent, getComponents, dom) => { | |||
let domNode = document.querySelector(dom) | |||
export const render = (getSystem, getStore, getComponent, getComponents, domNode) => { | |||
let App = (getComponent(getSystem, getStore, getComponents, "App", "root")) | |||
ReactDOM.render(( <App/> ), domNode) | |||
} | |||
@@ -1,21 +1,3 @@ | |||
html | |||
{ | |||
box-sizing: border-box; | |||
} | |||
*, | |||
*:before, | |||
*:after | |||
{ | |||
box-sizing: inherit; | |||
} | |||
body | |||
{ | |||
margin: 0; | |||
background: #fafafa; | |||
} | |||
.wrapper | |||
{ | |||
width: 100%; | |||
@@ -699,7 +681,6 @@ body | |||
.renderedMarkdown { | |||
p { | |||
@include text_body(); | |||
font-size: 14px; | |||
margin-top: 0px; | |||
margin-bottom: 0px; | |||
} | |||
@@ -227,8 +227,6 @@ span | |||
{ | |||
> span.model | |||
{ | |||
padding: 0 0 0 10px; | |||
.brace-close | |||
{ | |||
padding: 0 0 0 10px; | |||
@@ -236,6 +234,12 @@ span | |||
} | |||
} | |||
.prop-name | |||
{ | |||
display: inline-block; | |||
width: 100px; | |||
} | |||
.prop-type | |||
{ | |||
color: #55a; | |||
@@ -19,8 +19,8 @@ table | |||
&:first-of-type | |||
{ | |||
width: 100px; | |||
padding: 0; | |||
width: 124px; | |||
padding: 0 0 0 2em; | |||
} | |||
} | |||
} | |||
@@ -138,6 +138,14 @@ table | |||
@include text_code(#888); | |||
} | |||
.parameter__deprecated | |||
{ | |||
font-size: 12px; | |||
font-style: italic; | |||
@include text_code(#f00); | |||
} | |||
.table-container | |||
{ | |||
@@ -14,5 +14,6 @@ | |||
@import 'information'; | |||
@import 'authorize'; | |||
@import 'errors'; | |||
@include text_body(); | |||
@import 'split-pane-mode'; | |||
} |