Compare commits
9
Commits
cbt-run-e2e
...
v3.12.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49e0466641 | ||
|
|
ad57f5a549 | ||
|
|
ebf94dfccf | ||
|
|
6ba93ad43f | ||
|
|
54153dd929 | ||
|
|
83232dc2d8 | ||
|
|
ad43965d16 | ||
|
|
861cc65cff | ||
|
|
4900b11079 |
+1
-1
@@ -34,7 +34,7 @@ deploy:
|
||||
node: '6.9'
|
||||
after_success:
|
||||
- if [ $DOCKER_HUB_USERNAME ]; then
|
||||
docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
|
||||
docker login --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
|
||||
|
||||
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
DOCKER_IMAGE_TAG=$TRAVIS_TAG;
|
||||
|
||||
@@ -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.11.0 | 2018-02-09 | 2.0, 3.0 | [tag v3.11.0](https://github.com/swagger-api/swagger-ui/tree/v3.11.0)
|
||||
3.12.1 | 2018-03-09 | 2.0, 3.0 | [tag v3.12.1](https://github.com/swagger-api/swagger-ui/tree/v3.12.1)
|
||||
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)
|
||||
|
||||
Vendored
+14
-20
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+3
-3
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
# Plug points
|
||||
|
||||
Swagger-UI exposes most of its internal logic through the plugin system.
|
||||
|
||||
Often, it is beneficial to override the core internals to achieve custom behavior.
|
||||
|
||||
### Note: Semantic Versioning
|
||||
|
||||
Swagger-UI's internal APIs are _not_ part of our public contract, which means that they can change without the major version changing.
|
||||
|
||||
If your custom plugins wrap, extend, override, or consume any internal core APIs, we recommend specifying a specific minor version of Swagger-UI to use in your application, because they will _not_ change between patch versions.
|
||||
|
||||
If you're installing Swagger-UI via NPM, for example, you can do this by using a tilde:
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"swagger-ui": "~3.11.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `fn.opsFilter`
|
||||
|
||||
When using the `filter` option, tag names will be filtered by the user-provided value. If you'd like to customize this behavior, you can override the default `opsFilter` function.
|
||||
|
||||
For example, you can implement a multiple-phrase filter:
|
||||
|
||||
```js
|
||||
const MultiplePhraseFilterPlugin = function() {
|
||||
return {
|
||||
fn: {
|
||||
opsFilter: (taggedOps, phrase) => {
|
||||
const phrases = phrase.split(", ")
|
||||
|
||||
return taggedOps.filter((val, key) => {
|
||||
return phrases.some(item => key.indexOf(item) > -1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -2,6 +2,22 @@
|
||||
|
||||
A plugin is a function that returns an object - more specifically, the object may contain functions and components that augment and modify Swagger-UI's functionality.
|
||||
|
||||
### Note: Semantic Versioning
|
||||
|
||||
Swagger-UI's internal APIs are _not_ part of our public contract, which means that they can change without the major version changing.
|
||||
|
||||
If your custom plugins wrap, extend, override, or consume any internal core APIs, we recommend specifying a specific minor version of Swagger-UI to use in your application, because they will _not_ change between patch versions.
|
||||
|
||||
If you're installing Swagger-UI via NPM, for example, you can do this by using a tilde:
|
||||
|
||||
```js
|
||||
{
|
||||
"dependencies": {
|
||||
"swagger-ui": "~3.11.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Format
|
||||
|
||||
A plugin return value may contain any of these keys, where `stateKey` is a name for a piece of state:
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.11.0",
|
||||
"version": "3.12.1",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -83,7 +83,7 @@
|
||||
"scroll-to-element": "^2.0.0",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.5.0",
|
||||
"swagger-client": "^3.5.1",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -144,6 +144,7 @@
|
||||
"standard": "^10.0.2",
|
||||
"standard-loader": "^6.0.1",
|
||||
"style-loader": "0.18.2",
|
||||
"tachyons-sass": "^4.9.2",
|
||||
"url-loader": "0.5.9",
|
||||
"webpack": "^2.6.1",
|
||||
"webpack-bundle-size-analyzer": "^2.5.0"
|
||||
|
||||
@@ -46,7 +46,7 @@ export default class ArrayModel extends Component {
|
||||
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
|
||||
}
|
||||
{
|
||||
!description ? null :
|
||||
!description ? (properties.size ? <div className="markdown"></div> : null) :
|
||||
<Markdown source={ description } />
|
||||
}
|
||||
<span>
|
||||
|
||||
@@ -81,11 +81,11 @@ export default class Auths extends React.Component {
|
||||
}).toArray()
|
||||
}
|
||||
<div className="auth-btn-wrapper">
|
||||
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Done</Button>
|
||||
{
|
||||
nonOauthDefinitions.size === authorizedAuth.size ? <Button className="btn modal-btn auth" onClick={ this.logoutClick }>Logout</Button>
|
||||
: <Button type="submit" className="btn modal-btn auth authorize">Authorize</Button>
|
||||
}
|
||||
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Close</Button>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
|
||||
@@ -39,6 +39,13 @@ export default class Oauth2 extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
close = (e) => {
|
||||
e.preventDefault()
|
||||
let { authActions } = this.props
|
||||
|
||||
authActions.showDefinitions(false)
|
||||
}
|
||||
|
||||
authorize =() => {
|
||||
let { authActions, errActions, getConfigs, authSelectors } = this.props
|
||||
let configs = getConfigs()
|
||||
@@ -231,6 +238,7 @@ export default class Oauth2 extends React.Component {
|
||||
: <Button className="btn modal-btn auth authorize" onClick={ this.authorize }>Authorize</Button>
|
||||
)
|
||||
}
|
||||
<Button className="btn modal-btn auth btn-done" onClick={ this.close }>Close</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -101,7 +101,7 @@ class ValidatorImage extends React.Component {
|
||||
if (this.state.error) {
|
||||
return <img alt={"Error"} />
|
||||
} else if (!this.state.loaded) {
|
||||
return <img alt= {"Loading..."} />
|
||||
return null
|
||||
}
|
||||
return <img src={this.props.src} alt={this.props.alt} />
|
||||
}
|
||||
|
||||
@@ -24,11 +24,18 @@ export default class ParameterRow extends Component {
|
||||
|
||||
let { specSelectors, pathMethod, param } = props
|
||||
let defaultValue = param.get("default")
|
||||
let xExampleValue = param.get("x-example")
|
||||
let parameter = specSelectors.parameterWithMeta(pathMethod, param.get("name"), param.get("in"))
|
||||
let value = parameter ? parameter.get("value") : ""
|
||||
if ( defaultValue !== undefined && value === undefined ) {
|
||||
this.onChangeWrapper(defaultValue)
|
||||
|
||||
if( param.get("in") !== "body" ) {
|
||||
if ( xExampleValue !== undefined && value === undefined && specSelectors.isSwagger2() ) {
|
||||
this.onChangeWrapper(xExampleValue)
|
||||
} else if ( defaultValue !== undefined && value === undefined ) {
|
||||
this.onChangeWrapper(defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
|
||||
@@ -46,6 +46,7 @@ const sanitizeOptions = {
|
||||
"td": [ "colspan" ],
|
||||
"*": [ "class" ]
|
||||
},
|
||||
allowedSchemesByTag: { img: [ "http", "https", "data" ] },
|
||||
textFilter: function(text) {
|
||||
return text.replace(/"/g, "\"")
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
|
||||
this.state = {
|
||||
isEditBox: false,
|
||||
userDidModify: false,
|
||||
value: ""
|
||||
}
|
||||
}
|
||||
@@ -59,6 +60,11 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
this.onChange(this.sample(explicitMediaType))
|
||||
}
|
||||
|
||||
resetValueToSample = (explicitMediaType) => {
|
||||
this.setState({ userDidModify: false })
|
||||
this.setValueToSample(explicitMediaType)
|
||||
}
|
||||
|
||||
sample = (explicitMediaType) => {
|
||||
let { requestBody, mediaType } = this.props
|
||||
let schema = requestBody.getIn(["content", explicitMediaType || mediaType, "schema"]).toJS()
|
||||
@@ -78,6 +84,7 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
const isJson = /json/i.test(mediaType)
|
||||
const inputValue = isJson ? e.target.value.trim() : e.target.value
|
||||
|
||||
this.setState({ userDidModify: true })
|
||||
this.onChange(inputValue)
|
||||
}
|
||||
|
||||
@@ -87,13 +94,14 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
let {
|
||||
isExecute,
|
||||
getComponent,
|
||||
mediaType,
|
||||
} = this.props
|
||||
|
||||
const Button = getComponent("Button")
|
||||
const TextArea = getComponent("TextArea")
|
||||
const HighlightCode = getComponent("highlightCode")
|
||||
|
||||
let { value, isEditBox } = this.state
|
||||
let { value, isEditBox, userDidModify } = this.state
|
||||
|
||||
return (
|
||||
<div className="body-param">
|
||||
@@ -104,14 +112,18 @@ export default class RequestBodyEditor extends PureComponent {
|
||||
value={ value }/>)
|
||||
}
|
||||
<div className="body-param-options">
|
||||
{
|
||||
!isExecute ? null
|
||||
: <div className="body-param-edit">
|
||||
<Button className={isEditBox ? "btn cancel body-param__example-edit" : "btn edit body-param__example-edit"}
|
||||
onClick={this.toggleIsEditBox}>{ isEditBox ? "Cancel" : "Edit"}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
<div className="body-param-edit">
|
||||
{
|
||||
!isExecute ? null
|
||||
: <Button className={isEditBox ? "btn cancel body-param__example-edit" : "btn edit body-param__example-edit"}
|
||||
onClick={this.toggleIsEditBox}>{ isEditBox ? "Cancel" : "Edit"}
|
||||
</Button>
|
||||
|
||||
}
|
||||
{ userDidModify &&
|
||||
<Button className="btn ml3" onClick={() => { this.resetValueToSample(mediaType) }}>Reset</Button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -350,7 +350,7 @@ export function extractFileNameFromContentDispositionHeader(value){
|
||||
if (responseFilename !== null && responseFilename.length > 1) {
|
||||
return responseFilename[1]
|
||||
}
|
||||
return null
|
||||
return null
|
||||
}
|
||||
|
||||
// PascalCase, aka UpperCamelCase
|
||||
@@ -559,7 +559,7 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
|
||||
} else if ( type === "array" ) {
|
||||
let itemType
|
||||
|
||||
if ( !value.count() ) { return errors }
|
||||
if ( !listCheck || !value.count() ) { return errors }
|
||||
|
||||
itemType = paramDetails.getIn(["items", "type"])
|
||||
|
||||
|
||||
@@ -45,7 +45,10 @@ export default class Topbar extends React.Component {
|
||||
setSearch = (spec) => {
|
||||
let search = parseSearch()
|
||||
search["urls.primaryName"] = spec.name
|
||||
window.location.search = serializeSearch(search)
|
||||
const newUrl = `${window.location.protocol}//${window.location.host}${window.location.pathname}`
|
||||
if(window && window.history && window.history.pushState) {
|
||||
window.history.replaceState(null, "", `${newUrl}?${serializeSearch(search)}`)
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedUrl = (selectedUrl) => {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
.authorize
|
||||
{
|
||||
padding-right: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.swagger-ui
|
||||
{
|
||||
@import '~tachyons-sass/tachyons.scss';
|
||||
@import 'mixins';
|
||||
@import 'variables';
|
||||
@import 'colors';
|
||||
|
||||
@@ -24,6 +24,18 @@ describe("Markdown component", function() {
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img src="http://image.source" title="Image title"></p>\n</div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with https scheme", function() {
|
||||
const str = ``
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p><img src="https://image.source" title="Image title"></p>\n</div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with data scheme", function() {
|
||||
const str = `<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==">`
|
||||
const el = render(<Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="markdown"><p>` + str + `</p>\n</div>`)
|
||||
})
|
||||
|
||||
it("allows heading elements", function() {
|
||||
const str = `
|
||||
@@ -51,6 +63,18 @@ describe("Markdown component", function() {
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="http://image.source" title="Image title"></p></div></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with https scheme", function() {
|
||||
const str = ``
|
||||
const el = render(<OAS3Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div><p><img src="https://image.source" title="Image title"></p></div></div>`)
|
||||
})
|
||||
|
||||
it("allows image elements with data scheme", function() {
|
||||
const str = `<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==">`
|
||||
const el = render(<OAS3Markdown source={str} />)
|
||||
expect(el.html()).toEqual(`<div class="renderedMarkdown"><div>` + str + `</div></div>`)
|
||||
})
|
||||
|
||||
it("allows heading elements", function() {
|
||||
const str = `
|
||||
# h1
|
||||
|
||||
Reference in New Issue
Block a user