Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a068f78252 | ||
|
|
933da1e93a | ||
|
|
3c1a1780a6 | ||
|
|
bf1bc120fe | ||
|
|
fce31afa6c | ||
|
|
b73063578c | ||
|
|
cbd74b0c67 | ||
|
|
8e80ca9583 | ||
|
|
3ef50589e9 | ||
|
|
1d146394f3 | ||
|
|
e91573af39 | ||
|
|
2cc3e3c2d6 | ||
|
|
af7a99e901 | ||
|
|
7e1eb4e9a7 | ||
|
|
4f0cf53401 | ||
|
|
073eff4e10 | ||
|
|
cd7007d557 | ||
|
|
b76dcc2d4a | ||
|
|
b2af309cd5 | ||
|
|
7296a054c4 | ||
|
|
6b5063ead1 | ||
|
|
018491b4a7 | ||
|
|
74b4a3d598 | ||
|
|
51b04b3a26 | ||
|
|
f14d8067c4 | ||
|
|
c08f3c230b | ||
|
|
96f4b65dfa | ||
|
|
69fd57f17f | ||
|
|
f85fdb7835 | ||
|
|
15d43886a3 | ||
|
|
0e62d920e8 | ||
|
|
b6c3f91127 | ||
|
|
11e9bbfdbb | ||
|
|
d2c3078a79 | ||
|
|
dd11740359 | ||
|
|
8a1e447f0f | ||
|
|
ca808e9d18 | ||
|
|
f5e89dc02e | ||
|
|
2cff912261 | ||
|
|
5a5a4d016b | ||
|
|
f1f912a46f | ||
|
|
518e2ec732 | ||
|
|
862301e6df | ||
|
|
374ac9cbbb | ||
|
|
7d87c9d680 | ||
|
|
78336e99aa | ||
|
|
a7c90e2d77 | ||
|
|
87a23c7c9e | ||
|
|
d013e7a05c | ||
|
|
198f9b6874 | ||
|
|
210b20eea8 | ||
|
|
f755f80072 | ||
|
|
8137f25cc7 | ||
|
|
a8ff714eee | ||
|
|
494048e809 | ||
|
|
bcd36ff667 | ||
|
|
38ed6192c3 | ||
|
|
b9df212ccc | ||
|
|
22dc506b13 | ||
|
|
da7210d328 | ||
|
|
ca05b3e255 | ||
|
|
891c321c8a | ||
|
|
cecf0670b7 | ||
|
|
bb73dd49d8 | ||
|
|
eab557f470 | ||
|
|
ac25a5dac6 | ||
|
|
073313df6f | ||
|
|
26912b094f | ||
|
|
6f6f76caf4 | ||
|
|
bbb3035bac | ||
|
|
6841732367 | ||
|
|
1a417b3c6c | ||
|
|
aa327ed256 | ||
|
|
808f8d2827 | ||
|
|
4c40fa192b | ||
|
|
2c6bd5d988 | ||
|
|
b289d5992a | ||
|
|
5573f4d32d | ||
|
|
d6c498b5f3 | ||
|
|
a600280441 | ||
|
|
0f95724829 | ||
|
|
5ae195074f | ||
|
|
f5137da130 | ||
|
|
2bc6c5aa75 | ||
|
|
51dac3eea1 | ||
|
|
10b5c8ef8b | ||
|
|
e871871724 | ||
|
|
a6a02997e5 | ||
|
|
58e29934fd | ||
|
|
e0ecffd7c1 | ||
|
|
5a260971cc | ||
|
|
037dc71197 | ||
|
|
adf9f2d8aa | ||
|
|
06c82bb325 | ||
|
|
6cd66bb4f9 | ||
|
|
4e238ce889 | ||
|
|
1418653144 | ||
|
|
ca048f42a4 | ||
|
|
26a3ed26e8 | ||
|
|
84b408849d | ||
|
|
7790383ba6 | ||
|
|
32d7cd7204 | ||
|
|
4963c3016c | ||
|
|
0e00a68f7f | ||
|
|
754d57396a | ||
|
|
db66f56b83 | ||
|
|
8e5be08992 | ||
|
|
40d7740779 | ||
|
|
8b78d9bd13 | ||
|
|
5fc064e2ac | ||
|
|
f36a66a1b1 | ||
|
|
d5b79c70c9 | ||
|
|
35769f9b47 | ||
|
|
8e64c866e8 | ||
|
|
4b984e3c42 | ||
|
|
1794de1679 | ||
|
|
6a36b58977 | ||
|
|
7169ea32c9 |
@@ -0,0 +1,3 @@
|
||||
When reporting an issue, please provide the following details:
|
||||
- swagger-ui version
|
||||
- a swagger file reproducing the issue
|
||||
+20
-13
@@ -7,21 +7,29 @@ branches:
|
||||
only:
|
||||
- master
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
before_deploy: "npm run build-core"
|
||||
before_deploy:
|
||||
- npm run build
|
||||
env:
|
||||
- DOCKER_IMAGE_NAME=swaggerapi/swagger-ui
|
||||
deploy:
|
||||
provider: npm
|
||||
email: apiteam@swagger.io
|
||||
skip_cleanup: true
|
||||
api_key:
|
||||
secure: "IJkLaACa+rfERf1O5nwlqOyuo9sbul3FBhBt4Un9P+DvEet3AoDPV9NQVLd8SkmQYKGbGQWF4BIdjrO5nqFD6Te+JTeUX5Uo/DFS/fu9qw1xv0dQpvbJFuoYnnFlbzGTEs4CFa8lbu3ZromFHQGOQxRobjsG1Kf0dWFSSzmND3g="
|
||||
on:
|
||||
tags: true
|
||||
repo: swagger-api/swagger-ui
|
||||
node: '6.9'
|
||||
- provider: npm
|
||||
email: apiteam@swagger.io
|
||||
skip_cleanup: true
|
||||
api_key:
|
||||
secure: "IJkLaACa+rfERf1O5nwlqOyuo9sbul3FBhBt4Un9P+DvEet3AoDPV9NQVLd8SkmQYKGbGQWF4BIdjrO5nqFD6Te+JTeUX5Uo/DFS/fu9qw1xv0dQpvbJFuoYnnFlbzGTEs4CFa8lbu3ZromFHQGOQxRobjsG1Kf0dWFSSzmND3g="
|
||||
on:
|
||||
tags: true
|
||||
repo: swagger-api/swagger-ui
|
||||
node: '6.9'
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
script: swagger-ui-dist-package/deploy.sh
|
||||
on:
|
||||
tags: true
|
||||
repo: swagger-api/swagger-ui
|
||||
node: '6.9'
|
||||
after_success:
|
||||
- if [ $DOCKER_HUB_USERNAME ]; then
|
||||
- if [ $DOCKER_HUB_USERNAME ]; then
|
||||
docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD;
|
||||
|
||||
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
@@ -32,7 +40,7 @@ after_success:
|
||||
docker build -t $DOCKER_IMAGE_NAME .;
|
||||
if [ ! -z "$TRAVIS_TAG" ]; then
|
||||
docker tag $DOCKER_IMAGE_NAME $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||
docker push $DOCKER_IMAGE_NAME $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||
docker push $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||
docker tag $DOCKER_IMAGE_NAME $DOCKER_IMAGE_NAME:latest;
|
||||
docker push $DOCKER_IMAGE_NAME:latest;
|
||||
else
|
||||
@@ -40,4 +48,3 @@ after_success:
|
||||
docker push $DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ The OpenAPI Specification has undergone 4 revisions since initial creation in 20
|
||||
|
||||
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | Status
|
||||
------------------ | ------------ | -------------------------- | ----- | ------
|
||||
3.0.6 | 2017-03-19 | 2.0 | [tag v3.0.6](https://github.com/swagger-api/swagger-ui/tree/v3.0.6) |
|
||||
3.0.9 | 2017-03-19 | 2.0 | [tag v3.0.9](https://github.com/swagger-api/swagger-ui/tree/v3.0.9) |
|
||||
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) |
|
||||
2.0.24 | 2014-09-12 | 1.1, 1.2 | [tag v2.0.24](https://github.com/swagger-api/swagger-ui/tree/v2.0.24) |
|
||||
@@ -58,7 +58,7 @@ To help with the migration, here are the currently known issues with 3.X. This l
|
||||
- Relative path support for external files is not implemented.
|
||||
|
||||
### SwaggerUIBundle
|
||||
To use swagger-ui you should take a look at the [source of swagger-ui html page](https://github.com/swagger-api/swagger-ui/blob/master/dist/index.html) and customize it. This basically requires you to instantiate a SwaggerUi object and call load() on it as below:
|
||||
To use swagger-ui's bundles, you should take a look at the [source of swagger-ui html page](https://github.com/swagger-api/swagger-ui/blob/master/dist/index.html) and customize it. This basically requires you to instantiate a SwaggerUi object as below:
|
||||
|
||||
```javascript
|
||||
const ui = SwaggerUIBundle({
|
||||
@@ -75,6 +75,8 @@ To use swagger-ui you should take a look at the [source of swagger-ui html page]
|
||||
})
|
||||
```
|
||||
|
||||
If you'd like to use the bundle files via npm, check out the [`swagger-ui-dist` package](https://www.npmjs.com/package/swagger-ui-dist).
|
||||
|
||||
#### Parameters
|
||||
|
||||
Parameter Name | Description
|
||||
@@ -84,8 +86,35 @@ spec | A JSON object describing the OpenAPI Specification. When used, the `url`
|
||||
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.
|
||||
oauth2RedirectUrl | OAuth redirect URL
|
||||
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.
|
||||
configUrl | Configs URL
|
||||
|
||||
### Plugins
|
||||
|
||||
#### Topbar plugin
|
||||
Topbar plugin enables top bar with input for spec path and explore button. By default the plugin is enabled, and to disable it you need to remove Topbar plugin from presets in `src/standalone/index.js`:
|
||||
|
||||
```
|
||||
let preset = [
|
||||
// TopbarPlugin,
|
||||
ConfigsPlugin,
|
||||
() => {
|
||||
return {
|
||||
components: { StandaloneLayout }
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### Configs plugin
|
||||
Configs plugin allows to fetch external configs instead of passing them to `SwaggerUIBundle`. Fetched configs support two formats: JSON or yaml. The plugin is enabled by default.
|
||||
There are three options of passing config:
|
||||
- add a query parameter `config` with URL to a server where the configs are hosted. For ex. http://petstore.swagger.io/?configs=http://localhost:3001/config.yaml
|
||||
- add a config `configUrl` with URL to SwaggerUIBundle
|
||||
- change default configs in `swagger-config.yaml` *Note: after changing, the project must be re-built*
|
||||
|
||||
These options can be used altogether, the order of inheritance is following (from the lowest priority to the highest):
|
||||
`swagger-config.yaml` -> config passed to `SwaggerUIBundle` -> config fetched from `configUrl` passed to `SwaggerUIBundle` -> config fetched from URL passed as a query parameter `config`
|
||||
|
||||
## CORS Support
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<body onload="run()">
|
||||
</body>
|
||||
</html>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var isValid, qp, arr;
|
||||
|
||||
qp = (window.location.hash || location.search).substring(1);
|
||||
|
||||
arr = qp.split("&")
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value)
|
||||
}
|
||||
) : {}
|
||||
|
||||
isValid = qp.state === sentState
|
||||
|
||||
if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback(oauth2.auth);
|
||||
} else {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: "Authorization failed: no accessCode received from the server"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
</script>
|
||||
Vendored
+1
-1
@@ -90,4 +90,4 @@ window.onload = function() {
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Vendored
+7
-37
@@ -8,11 +8,13 @@
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var isValid, qp;
|
||||
var isValid, qp, arr;
|
||||
|
||||
qp = (window.location.hash || location.search).substring(1);
|
||||
|
||||
qp = qp ? JSON.parse('{"' + qp.replace(/&/g, '","').replace(/=/g, '":"') + '"}',
|
||||
arr = qp.split("&")
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value)
|
||||
}
|
||||
@@ -33,51 +35,19 @@
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
createForm(oauth2.auth, qp).submit();
|
||||
oauth2.callback(oauth2.auth);
|
||||
} else {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: "Authorization failed: no accessCode came from the server"
|
||||
message: "Authorization failed: no accessCode received from the server"
|
||||
});
|
||||
window.close();
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid});
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
function createForm(auth, qp) {
|
||||
var form = document.createElement("form");
|
||||
var schema = auth.schema;
|
||||
var action = schema.get("tokenUrl");
|
||||
var name, input;
|
||||
|
||||
var fields = {
|
||||
code: qp.code,
|
||||
"redirect_uri": location.protocol + "//" + location.host + location.pathname,
|
||||
"grant_type": "authorization_code",
|
||||
"client_secret": auth.clientSecret,
|
||||
"client_id": auth.clientId
|
||||
}
|
||||
|
||||
for ( name in fields ) {
|
||||
input = document.createElement("input");
|
||||
input.name = name;
|
||||
input.value = fields[name];
|
||||
input.type = "hidden";
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
|
||||
form.method = "POST";
|
||||
form.action = action;
|
||||
|
||||
document.body.appendChild(form);
|
||||
|
||||
return form;
|
||||
window.close();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
Vendored
+47
-47
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AA0dA;AAkoJA;AAyiCA;;;;;AAskCA;AA66IA;AA20FA;AAg3GA;AAonEA;AA+9CA;AA6/CA;AA+rCA;AA+3EA;AA68HA;;;;;;;;;;;;;;AA8tGA;AAyoIA;AAiuJA;AA8kHA;AAonGA;AAukEA;AA02DA;AAyxDA;AAw6BA;;;;;;AAs0EA;AA24FA;;;;;AAy3CA;AA2qFA;AAw2CA;AA2kCA;AAq/CA;AAwwEA;AA48FA;;;;;;;;;AA81BA;AA2zIA;AAi4DA;AAqlDA;;;;;;AA4kCA;AA8iHA;AAipGA","sourceRoot":""}
|
||||
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAoTA;;;;;;AAoIA;AAi7FA;AAmtCA;AAi0IA;AA2pJA;AA+uFA;AA2rGA;AAgiFA;AA0rFA;AAk9CA;AA2hDA;AA4rCA;AAg6EA;;;;;AA4gCA;AA02JA;;;;;;;;;;;;;;AAuyEA;AA4mIA;AAquJA;AAwsHA;AA2mGA;AAiiEA;AAq4DA;AA+2DA;AAmfA;;;;;;AAmrFA;AA62FA;;;;;AAy3CA;AA2qFA;AAw2CA;AAqkCA;AA++CA;AAsiFA;AAk2FA;;;;;;;;;AAm/CA;AA2zIA;AAk4DA;AAolDA","sourceRoot":""}
|
||||
Vendored
+15
-3
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA6PA;AAyiGA","sourceRoot":""}
|
||||
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA8QA;AAitGA;AA+vFA;;;;;;AA6eA;AAkvFA;AAu+CA;AAo+CA;AAgrCA;AAgyEA","sourceRoot":""}
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+9
-9
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAuwCA;AAoyHA;AAmxHA;AAo8FA;AAooCA;AAghCA;AA0gCA;AA06BA","sourceRoot":""}
|
||||
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AAyxCA;AAoyHA;AAuxHA;AAy4FA;AA2sCA;AAmgCA;AA0iCA;AA64BA","sourceRoot":""}
|
||||
+5
-2
@@ -39,7 +39,10 @@ fi
|
||||
|
||||
if [[ -n "$VALIDATOR_URL" ]]; then
|
||||
sed -i "s|.*validatorUrl:.*$||g" $INDEX_FILE
|
||||
sed -i "s|\(url: url,.*\)|\1\n validatorUrl: \"${VALIDATOR_URL}\",|g" $INDEX_FILE
|
||||
TMP_VU="$VALIDATOR_URL"
|
||||
[[ "$VALIDATOR_URL" != "null" && "$VALIDATOR_URL" != "undefined" ]] && TMP_VU="\"${VALIDATOR_URL}\""
|
||||
sed -i "s|\(url: .*,\)|\1\n validatorUrl: ${TMP_VU},|g" $INDEX_FILE
|
||||
unset TMP_VU
|
||||
fi
|
||||
|
||||
exec nginx -g 'daemon off;'
|
||||
exec nginx -g 'daemon off;'
|
||||
|
||||
@@ -4,9 +4,13 @@ var webpack = require('webpack')
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
var deepExtend = require('deep-extend')
|
||||
var autoprefixer = require('autoprefixer')
|
||||
const {gitDescribeSync} = require('git-describe');
|
||||
|
||||
var loadersByExtension = require('./build-tools/loadersByExtension')
|
||||
|
||||
var pkg = require('./package.json')
|
||||
const gitInfo = gitDescribeSync(__dirname)
|
||||
|
||||
module.exports = function(options) {
|
||||
|
||||
// Special options, that have logic in this file
|
||||
@@ -60,7 +64,13 @@ module.exports = function(options) {
|
||||
'process.env': {
|
||||
NODE_ENV: specialOptions.minimize ? JSON.stringify('production') : null,
|
||||
WEBPACK_INLINE_STYLES: !Boolean(specialOptions.separateStylesheets)
|
||||
|
||||
},
|
||||
'buildInfo': JSON.stringify({
|
||||
PACKAGE_VERSION: (pkg.version),
|
||||
GIT_COMMIT: gitInfo.hash,
|
||||
GIT_DIRTY: gitInfo.dirty
|
||||
})
|
||||
}))
|
||||
|
||||
var cssLoader = 'css-loader!postcss-loader'
|
||||
|
||||
+5
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "swagger-ui",
|
||||
"version": "3.0.6",
|
||||
"version": "3.0.9",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
@@ -36,10 +36,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"base64-js": "^1.2.0",
|
||||
"brace": "0.7.0",
|
||||
"deep-extend": "0.4.1",
|
||||
"expect": "1.20.2",
|
||||
"getbase": "^2.8.2",
|
||||
"ieee754": "^1.1.8",
|
||||
"immutable": "^3.x.x",
|
||||
"js-yaml": "^3.5.5",
|
||||
"less": "2.7.1",
|
||||
@@ -67,7 +69,7 @@
|
||||
"reselect": "2.5.3",
|
||||
"serialize-error": "2.0.0",
|
||||
"shallowequal": "0.2.2",
|
||||
"swagger-client": "^3.0.5",
|
||||
"swagger-client": "^3.0.9",
|
||||
"url-parse": "^1.1.8",
|
||||
"whatwg-fetch": "0.11.1",
|
||||
"worker-loader": "^0.7.1",
|
||||
@@ -93,6 +95,7 @@
|
||||
"eslint-plugin-react": "^6.10.3",
|
||||
"extract-text-webpack-plugin": "0.8.2",
|
||||
"file-loader": "0.8.4",
|
||||
"git-describe": "^4.0.1",
|
||||
"html-webpack-plugin": "^2.28.0",
|
||||
"imports-loader": "0.6.5",
|
||||
"json-loader": "0.5.3",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
name: swagger-ui
|
||||
version: master
|
||||
summary: The World's Most Popular API Framework
|
||||
description: |
|
||||
Swagger UI is part of the Swagger project. The Swagger project allows you to
|
||||
produce, visualize and consume your OWN RESTful services. No proxy or 3rd
|
||||
party services required. Do it your own way.
|
||||
|
||||
Swagger UI is a dependency-free collection of HTML, Javascript, and CSS
|
||||
assets that dynamically generate beautiful documentation and sandbox from a
|
||||
Swagger-compliant API. Because Swagger UI has no dependencies, you can host
|
||||
it in any server environment, or on your local machine.
|
||||
|
||||
grade: devel
|
||||
confinement: strict
|
||||
|
||||
apps:
|
||||
swagger-ui:
|
||||
command: sh -c \"cd $SNAP/lib/node_modules/swagger-ui/dist && http-server -a localhost -p 8080\"
|
||||
daemon: simple
|
||||
plugs: [network, network-bind]
|
||||
|
||||
parts:
|
||||
swagger-ui:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
npm-run: [build]
|
||||
node-packages: [handlebars, http-server]
|
||||
@@ -64,11 +64,10 @@ export default class ApiKeyAuth extends React.Component {
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Value:</label>
|
||||
<Col>
|
||||
{
|
||||
value || <Input type="text" onChange={ this.onChange }/>
|
||||
}
|
||||
</Col>
|
||||
{
|
||||
value ? <code> ****** </code>
|
||||
: <Col><Input type="text" onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
errors.valueSeq().map( (error, key) => {
|
||||
|
||||
@@ -63,19 +63,23 @@ export default class BasicAuth extends React.Component {
|
||||
source={ schema.get("description") } />
|
||||
</Row>
|
||||
<Row>
|
||||
<Col tablet={2} desktop={2}>username:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
<label>Username:</label>
|
||||
{
|
||||
username ? <code> { username } </code>
|
||||
: <Col><Input type="text" required="required" name="username" onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Row>
|
||||
<Row>
|
||||
<label>Password:</label>
|
||||
{
|
||||
username || <Input type="text" required="required" name="username" onChange={ this.onChange }/>
|
||||
username ? <code> ****** </code>
|
||||
: <Col><Input required="required"
|
||||
autoComplete="new-password"
|
||||
name="password"
|
||||
type="password"
|
||||
onChange={ this.onChange }/></Col>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
!username && <Row>
|
||||
<Col tablet={2} desktop={2}>password:</Col>
|
||||
<Col tablet={10} desktop={10}><Input required="required" autoComplete="new-password" name="password" type="password" onChange={ this.onChange }/></Col>
|
||||
</Row>
|
||||
}
|
||||
{
|
||||
errors.valueSeq().map( (error, key) => {
|
||||
return <AuthError error={ error }
|
||||
|
||||
@@ -26,7 +26,7 @@ export default class Oauth2 extends React.Component {
|
||||
let username = auth && auth.get("username") || ""
|
||||
let clientId = auth && auth.get("clientId") || ""
|
||||
let clientSecret = auth && auth.get("clientSecret") || ""
|
||||
let passwordType = auth && auth.get("passwordType") || "none"
|
||||
let passwordType = auth && auth.get("passwordType") || "basic"
|
||||
|
||||
this.state = {
|
||||
name: name,
|
||||
@@ -108,66 +108,69 @@ export default class Oauth2 extends React.Component {
|
||||
<p className="flow">Flow: <code>{ schema.get("flow") }</code></p>
|
||||
|
||||
{
|
||||
flow === PASSWORD && ( !isAuthorized || isAuthorized && this.state.username) && <Row>
|
||||
<Col tablet={2} desktop={2}>username:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
flow !== PASSWORD ? null
|
||||
: <Row>
|
||||
<Row>
|
||||
<label htmlFor="oauth_username">username:</label>
|
||||
{
|
||||
isAuthorized ? <code> { this.state.username } </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="oauth_username" type="text" data-name="username" onChange={ this.onInputChange }/>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.username }</span>
|
||||
: <input type="text" data-name="username" onChange={ this.onInputChange }/>
|
||||
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<label htmlFor="oauth_password">password:</label>
|
||||
{
|
||||
isAuthorized ? <code> ****** </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="oauth_password" type="password" data-name="password" onChange={ this.onInputChange }/>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
<Row>
|
||||
<label htmlFor="password_type">type:</label>
|
||||
{
|
||||
isAuthorized ? <code> { this.state.passwordType } </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<select id="password_type" data-name="passwordType" onChange={ this.onInputChange }>
|
||||
<option value="basic">Basic auth</option>
|
||||
<option value="request-body">Request body</option>
|
||||
<option value="query">Query parameters</option>
|
||||
</select>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
flow === PASSWORD && !isAuthorized && <Row>
|
||||
<Col tablet={2} desktop={2}>password:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
<input type="password" data-name="password" onChange={ this.onInputChange }/>
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
flow === PASSWORD && <Row>
|
||||
<Col tablet={2} desktop={2}>type:</Col>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.passwordType }</span>
|
||||
: <select data-name="passwordType" onChange={ this.onInputChange }>
|
||||
<option value="none">None or other</option>
|
||||
<option value="basic">Basic auth</option>
|
||||
<option value="request">Request body</option>
|
||||
</select>
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) &&
|
||||
( flow === APPLICATION || flow === IMPLICIT || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) &&
|
||||
( !isAuthorized || isAuthorized && this.state.clientId) && <Row>
|
||||
<label htmlFor="client_id">client_id:</label>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.clientId }</span>
|
||||
: <input id="client_id" type="text" required={ flow === PASSWORD } data-name="clientId"
|
||||
{
|
||||
isAuthorized ? <code> ****** </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="client_id" type="text" required={ flow === PASSWORD } data-name="clientId"
|
||||
onChange={ this.onInputChange }/>
|
||||
}
|
||||
</Col>
|
||||
</Col>
|
||||
}
|
||||
</Row>
|
||||
}
|
||||
|
||||
{
|
||||
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "none") ) && <Row>
|
||||
( flow === APPLICATION || flow === ACCESS_CODE || ( flow === PASSWORD && this.state.passwordType!== "basic") ) && <Row>
|
||||
<label htmlFor="client_secret">client_secret:</label>
|
||||
<Col tablet={10} desktop={10}>
|
||||
{
|
||||
isAuthorized ? <span>{ this.state.clientSecret }</span>
|
||||
: <input id="client_secret" type="text" data-name="clientSecret"
|
||||
{
|
||||
isAuthorized ? <code> ****** </code>
|
||||
: <Col tablet={10} desktop={10}>
|
||||
<input id="client_secret" type="text" data-name="clientSecret"
|
||||
onChange={ this.onInputChange }/>
|
||||
}
|
||||
</Col>
|
||||
</Col>
|
||||
}
|
||||
|
||||
</Row>
|
||||
}
|
||||
|
||||
@@ -179,11 +182,11 @@ export default class Oauth2 extends React.Component {
|
||||
<Row key={ name }>
|
||||
<div className="checkbox">
|
||||
<Input data-value={ name }
|
||||
id={`${name}-checkbox`}
|
||||
id={`${name}-checkbox-${this.state.name}`}
|
||||
disabled={ isAuthorized }
|
||||
type="checkbox"
|
||||
onChange={ this.onScopeChange }/>
|
||||
<label htmlFor={`${name}-checkbox`}>
|
||||
<label htmlFor={`${name}-checkbox-${this.state.name}`}>
|
||||
<span className="item"></span>
|
||||
<div className="text">
|
||||
<p className="name">{name}</p>
|
||||
|
||||
@@ -16,7 +16,7 @@ export class Container extends React.Component {
|
||||
if(fullscreen)
|
||||
return <section {...rest}/>
|
||||
|
||||
let containerClass = "container" + (full ? "-full" : "")
|
||||
let containerClass = "swagger-container" + (full ? "-full" : "")
|
||||
return (
|
||||
<section {...rest} className={xclass(rest.className, containerClass)}/>
|
||||
)
|
||||
@@ -127,7 +127,7 @@ export const Input = (props) => <input {...props} />
|
||||
|
||||
export class Select extends React.Component {
|
||||
static propTypes = {
|
||||
allowedValues: PropTypes.object,
|
||||
allowedValues: PropTypes.array,
|
||||
value: PropTypes.any,
|
||||
onChange: PropTypes.func,
|
||||
multiple: PropTypes.bool,
|
||||
|
||||
@@ -55,9 +55,10 @@ export default class ParamBody extends Component {
|
||||
let isXml = /xml/i.test(consumesValue)
|
||||
let paramValue = isXml ? parameter.get("value_xml") : parameter.get("value")
|
||||
|
||||
if ( paramValue ) {
|
||||
this.setState({ value: paramValue })
|
||||
this.onChange(paramValue, {isXml: isXml, isEditBox: isExecute})
|
||||
if ( paramValue !== undefined ) {
|
||||
let val = !paramValue && !isXml ? "{}" : paramValue
|
||||
this.setState({ value: val })
|
||||
this.onChange(val, {isXml: isXml, isEditBox: isExecute})
|
||||
} else {
|
||||
if (isXml) {
|
||||
this.onChange(this.sample("xml"), {isXml: isXml, isEditBox: isExecute})
|
||||
|
||||
@@ -28,11 +28,25 @@ export default class ParameterRow extends Component {
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
let { specSelectors, pathMethod, param } = props
|
||||
let example = param.get("example")
|
||||
let defaultValue = param.get("default")
|
||||
let parameter = specSelectors.getParameter(pathMethod, param.get("name"))
|
||||
let value = parameter ? parameter.get("value") : ""
|
||||
if ( defaultValue !== undefined && value === undefined ) {
|
||||
this.onChangeWrapper(defaultValue)
|
||||
let paramValue = parameter ? parameter.get("value") : undefined
|
||||
let enumValue = parameter ? parameter.get("enum") : undefined
|
||||
let value
|
||||
|
||||
if ( paramValue !== undefined ) {
|
||||
value = paramValue
|
||||
} else if ( example !== undefined ) {
|
||||
value = example
|
||||
} else if ( defaultValue !== undefined) {
|
||||
value = defaultValue
|
||||
} else if ( param.get("required") && enumValue && enumValue.size ) {
|
||||
value = enumValue.first()
|
||||
}
|
||||
|
||||
if ( value !== undefined ) {
|
||||
this.onChangeWrapper(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import deepExtend from "deep-extend"
|
||||
|
||||
import System from "core/system"
|
||||
import win from "core/window"
|
||||
import ApisPreset from "core/presets/apis"
|
||||
import * as AllPlugins from "core/plugins/all"
|
||||
import { filterConfigs } from "plugins/configs"
|
||||
import { parseSeach } from "core/utils"
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const { GIT_DIRTY, GIT_COMMIT, PACKAGE_VERSION } = buildInfo
|
||||
|
||||
module.exports = function SwaggerUI(opts) {
|
||||
|
||||
win.versions = win.versions || {}
|
||||
win.versions.swaggerUi = `${PACKAGE_VERSION}/${GIT_COMMIT || "unknown"}${GIT_DIRTY ? "-dirty" : ""}`
|
||||
|
||||
const defaults = {
|
||||
// Some general settings, that we floated to the top
|
||||
dom_id: null,
|
||||
|
||||
@@ -150,9 +150,9 @@ export class JsonSchema_array extends Component {
|
||||
(errors.length ? <span style={{ color: "red", fortWeight: "bold" }}>{ errors[0] }</span> : null) :
|
||||
value.map( (item,i) => {
|
||||
let schema = Object.assign({}, itemSchema)
|
||||
let err = errors.filter((err) => err.index === i)
|
||||
if ( err.length ) {
|
||||
schema.errors = [ err[0].error + i ]
|
||||
if ( errors.length ) {
|
||||
let err = errors.filter((err) => err.index === i)
|
||||
if (err.length) schema.errors = [ err[0].error + i ]
|
||||
}
|
||||
return (
|
||||
<div key={i} className="json-schema-form-item">
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import win from "core/window"
|
||||
import { btoa } from "core/utils"
|
||||
|
||||
export default function authorize ( auth, authActions, errActions, configs ) {
|
||||
let { schema, scopes, name, clientId } = auth
|
||||
|
||||
let redirectUrl = configs.oauth2RedirectUrl
|
||||
let scopeSeparator = " "
|
||||
let state = name
|
||||
let state = btoa(new Date())
|
||||
let flow = schema.get("flow")
|
||||
let url
|
||||
|
||||
@@ -15,7 +16,7 @@ export default function authorize ( auth, authActions, errActions, configs ) {
|
||||
}
|
||||
|
||||
if (flow === "application") {
|
||||
authActions.authorizeOauth2Application(auth)
|
||||
authActions.authorizeApplication(auth)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ export default function authorize ( auth, authActions, errActions, configs ) {
|
||||
win.swaggerUIRedirectOauth2 = {
|
||||
auth: auth,
|
||||
state: state,
|
||||
callback: authActions.preAuthorizeOauth2,
|
||||
callback: flow === "implicit" ? authActions.preAuthorizeImplicit : authActions.authorizeAccessCode,
|
||||
errCb: errActions.newAuthErr
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import win from "core/window"
|
||||
import { btoa } from "core/utils"
|
||||
import { btoa, buildFormData } from "core/utils"
|
||||
|
||||
export const SHOW_AUTH_POPUP = "show_popup"
|
||||
export const AUTHORIZE = "authorize"
|
||||
@@ -31,7 +31,7 @@ export function logout(payload) {
|
||||
}
|
||||
}
|
||||
|
||||
export const preAuthorizeOauth2 = (payload) => ( { authActions, errActions } ) => {
|
||||
export const preAuthorizeImplicit = (payload) => ( { authActions, errActions } ) => {
|
||||
let { auth , token, isValid } = payload
|
||||
let { schema, name } = auth
|
||||
let flow = schema.get("flow")
|
||||
@@ -68,29 +68,72 @@ export function authorizeOauth2(payload) {
|
||||
}
|
||||
}
|
||||
|
||||
export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } ) => {
|
||||
export const authorizePassword = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, name, username, password, passwordType, clientId, clientSecret } = auth
|
||||
let req = {
|
||||
url: schema.get("tokenUrl"),
|
||||
method: "post",
|
||||
headers: {
|
||||
"content-type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
query: {
|
||||
grant_type: "password",
|
||||
username,
|
||||
password,
|
||||
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
||||
let form = {
|
||||
grant_type: "password",
|
||||
scopes: encodeURIComponent(auth.scopes.join(scopeSeparator))
|
||||
}
|
||||
let query = {}
|
||||
let headers = {}
|
||||
|
||||
if ( passwordType === "basic") {
|
||||
headers.Authorization = "Basic " + btoa(username + ":" + password)
|
||||
} else {
|
||||
Object.assign(form, {username}, {password})
|
||||
if ( passwordType === "query") {
|
||||
if ( clientId ) { query.client_id = clientId }
|
||||
if ( clientSecret ) { query.client_secret = clientSecret }
|
||||
} else {
|
||||
Object.assign(form, {client_id: clientId}, {client_secret: clientSecret})
|
||||
}
|
||||
}
|
||||
|
||||
if ( passwordType === "basic") {
|
||||
req.headers.authorization = "Basic " + btoa(clientId + ":" + clientSecret)
|
||||
} else if ( passwordType === "request") {
|
||||
req.query = Object.assign(req.query, { client_id: clientId, client_secret: clientSecret })
|
||||
return authActions.authorizeRequest({ body: buildFormData(form), url: schema.get("tokenUrl"), name, headers, query, auth})
|
||||
}
|
||||
|
||||
export const authorizeApplication = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, scopes, name, clientId, clientSecret } = auth
|
||||
let form = {
|
||||
grant_type: "client_credentials",
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
scope: scopes.join(scopeSeparator)
|
||||
}
|
||||
return fn.fetch(req)
|
||||
.then(( response ) => {
|
||||
|
||||
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth })
|
||||
}
|
||||
|
||||
export const authorizeAccessCode = ( auth ) => ( { authActions } ) => {
|
||||
let { schema, name, clientId, clientSecret } = auth
|
||||
let form = {
|
||||
grant_type: "authorization_code",
|
||||
code: auth.code,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret
|
||||
}
|
||||
|
||||
return authActions.authorizeRequest({body: buildFormData(form), name, url: schema.get("tokenUrl"), auth})
|
||||
|
||||
}
|
||||
|
||||
export const authorizeRequest = ( data ) => ( { fn, authActions, errActions } ) => {
|
||||
let { body, query={}, headers={}, name, url, auth } = data
|
||||
|
||||
let _headers = Object.assign({
|
||||
"Accept":"application/json, text/plain, */*",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
}, headers)
|
||||
|
||||
fn.fetch({
|
||||
url: url,
|
||||
method: "post",
|
||||
headers: _headers,
|
||||
query: query,
|
||||
body: body
|
||||
})
|
||||
.then(function (response) {
|
||||
let token = JSON.parse(response.data)
|
||||
let error = token && ( token.error || "" )
|
||||
let parseError = token && ( token.parseError || "" )
|
||||
@@ -115,39 +158,14 @@ export const authorizePassword = ( auth ) => ( { fn, authActions, errActions } )
|
||||
return
|
||||
}
|
||||
|
||||
authActions.authorizeOauth2({ auth, token })
|
||||
authActions.authorizeOauth2({ auth, token})
|
||||
})
|
||||
.catch(err => { errActions.newAuthErr( err ) })
|
||||
}
|
||||
|
||||
export const authorizeOauth2Application = ( auth ) => ( { fn, authActions, errActions } ) => {
|
||||
let { schema, scopes, name, clientId, clientSecret } = auth
|
||||
|
||||
fn.fetch(schema.get("tokenUrl"), {
|
||||
method: "post", headers: {
|
||||
"Accept":"application/json, text/plain, */*",
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: "grant_type=client_credentials" +
|
||||
"&client_id=" + encodeURIComponent(clientId) +
|
||||
"&client_secret=" + encodeURIComponent(clientSecret) +
|
||||
"&scope=" + encodeURIComponent(scopes.join(scopeSeparator))
|
||||
})
|
||||
.then(function (response) {
|
||||
if ( !response.ok ) {
|
||||
.catch(e => {
|
||||
let err = new Error(e)
|
||||
errActions.newAuthErr( {
|
||||
authId: name,
|
||||
level: "error",
|
||||
source: "auth",
|
||||
message: response.statusText
|
||||
} )
|
||||
return
|
||||
} else {
|
||||
response.json()
|
||||
.then(function (json){
|
||||
authActions.authorizeOauth2({ auth, token: json})
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(err => { errActions.newAuthErr( err ) })
|
||||
message: err.message
|
||||
} ) })
|
||||
}
|
||||
|
||||
@@ -97,7 +97,11 @@ export default {
|
||||
},
|
||||
|
||||
[UPDATE_OPERATION_VALUE]: (state, { payload: { path, value, key } }) => {
|
||||
return state.setIn(["resolved", "paths", ...path, key], fromJS(value))
|
||||
let operationPath = ["resolved", "paths", ...path]
|
||||
if(!state.getIn(operationPath)) {
|
||||
return state
|
||||
}
|
||||
return state.setIn([...operationPath, key], fromJS(value))
|
||||
},
|
||||
|
||||
[CLEAR_RESPONSE]: (state, { payload: { path, method } } ) =>{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createSelector } from "reselect"
|
||||
import { sorters } from "core/utils"
|
||||
import { fromJS, Set, Map, List } from "immutable"
|
||||
|
||||
const DEFAULT_TAG = "default"
|
||||
@@ -198,13 +199,16 @@ export const operationsWithTags = createSelector(
|
||||
}
|
||||
)
|
||||
|
||||
export const taggedOperations = createSelector(
|
||||
state,
|
||||
operationsWithTags,
|
||||
(state, tagMap) => {
|
||||
return tagMap.map((ops, tag) => Map({tagDetails: tagDetails(state, tag), operations: ops}))
|
||||
}
|
||||
)
|
||||
export const taggedOperations = ( state ) =>( { getConfigs } ) => {
|
||||
let { operationsSorter }= getConfigs()
|
||||
|
||||
return operationsWithTags(state).map((ops, tag) => {
|
||||
let sortFn = typeof operationsSorter === "function" ? operationsSorter
|
||||
: sorters.operationsSorter[operationsSorter]
|
||||
let operations = !sortFn ? ops : ops.sort(sortFn)
|
||||
|
||||
return Map({tagDetails: tagDetails(state, tag), operations: operations})})
|
||||
}
|
||||
|
||||
export const responses = createSelector(
|
||||
state,
|
||||
@@ -294,8 +298,8 @@ export const operationScheme = ( state, path, method ) => {
|
||||
let url = state.get("url")
|
||||
let matchResult = url.match(/^([a-z][a-z0-9+\-.]*):/)
|
||||
let urlScheme = Array.isArray(matchResult) ? matchResult[1] : null
|
||||
|
||||
return state.getIn(["scheme", path, method]) || state.getIn(["scheme", "_defaultScheme"]) || urlScheme || "http"
|
||||
|
||||
return state.getIn(["scheme", path, method]) || state.getIn(["scheme", "_defaultScheme"]) || urlScheme || ""
|
||||
}
|
||||
|
||||
export const canExecuteScheme = ( state, path, method ) => {
|
||||
|
||||
+3
-4
@@ -2,7 +2,6 @@ import { createStore, applyMiddleware, bindActionCreators, compose } from "redux
|
||||
import Im, { fromJS, Map } from "immutable"
|
||||
import deepExtend from "deep-extend"
|
||||
import { combineReducers } from "redux-immutable"
|
||||
import assign from "object-assign"
|
||||
import serializeError from "serialize-error"
|
||||
import { NEW_THROWN_ERR } from "corePlugins/err/actions"
|
||||
import win from "core/window"
|
||||
@@ -74,7 +73,7 @@ export default class Store {
|
||||
let dispatch = this.getStore().dispatch
|
||||
let getState = this.getStore().getState
|
||||
|
||||
this.boundSystem = assign({},
|
||||
this.boundSystem = Object.assign({},
|
||||
this.getRootInjects(),
|
||||
this.getWrappedAndBoundActions(dispatch),
|
||||
this.getBoundSelectors(getState, this.getSystem),
|
||||
@@ -92,7 +91,7 @@ export default class Store {
|
||||
}
|
||||
|
||||
getRootInjects() {
|
||||
return assign({
|
||||
return Object.assign({
|
||||
getSystem: this.getSystem,
|
||||
getStore: this.getStore.bind(this),
|
||||
getComponents: this.getComponents.bind(this),
|
||||
@@ -251,7 +250,7 @@ export default class Store {
|
||||
|
||||
getMapStateToProps() {
|
||||
return () => {
|
||||
let obj = assign({}, this.getSystem())
|
||||
let obj = Object.assign({}, this.getSystem())
|
||||
return obj
|
||||
}
|
||||
}
|
||||
|
||||
+20
-2
@@ -1,5 +1,4 @@
|
||||
import Im from "immutable"
|
||||
import assign from "object-assign"
|
||||
import shallowEqual from "shallowequal"
|
||||
|
||||
import camelCase from "lodash/camelCase"
|
||||
@@ -85,7 +84,7 @@ export function objReduce(obj, fn) {
|
||||
return Object.keys(obj).reduce((newObj, key) => {
|
||||
let res = fn(obj[key], key)
|
||||
if(res && typeof res === "object")
|
||||
assign(newObj, res)
|
||||
Object.assign(newObj, res)
|
||||
return newObj
|
||||
}, {})
|
||||
}
|
||||
@@ -559,3 +558,22 @@ export const btoa = (str) => {
|
||||
|
||||
return buffer.toString("base64")
|
||||
}
|
||||
|
||||
export const sorters = {
|
||||
operationsSorter: {
|
||||
alpha: (a, b) => a.get("path").localeCompare(b.get("path")),
|
||||
method: (a, b) => a.get("method").localeCompare(b.get("method"))
|
||||
}
|
||||
}
|
||||
|
||||
export const buildFormData = (data) => {
|
||||
let formArr = []
|
||||
|
||||
for (let name in data) {
|
||||
let val = data[name]
|
||||
if (val !== undefined && val !== "") {
|
||||
formArr.push([name, "=", encodeURIComponent(val).replace(/%20/g,"+")].join(""))
|
||||
}
|
||||
}
|
||||
return formArr.join("&")
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ export default class Topbar extends React.Component {
|
||||
this.setState({url: value})
|
||||
}
|
||||
|
||||
downloadUrl = () => {
|
||||
downloadUrl = (e) => {
|
||||
this.props.specActions.updateUrl(this.state.url)
|
||||
this.props.specActions.download(this.state.url)
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -43,10 +44,10 @@ export default class Topbar extends React.Component {
|
||||
<img height="30" width="30" src={ Logo } alt="Swagger UX"/>
|
||||
<span>swagger</span>
|
||||
</Link>
|
||||
<div className="download-url-wrapper">
|
||||
<form className="download-url-wrapper" onSubmit={this.downloadUrl}>
|
||||
<input className="download-url-input" type="text" onChange={ this.onUrlChange } value={this.state.url} disabled={isLoading} style={inputStyle} />
|
||||
<Button className="download-url-button" onClick={ this.downloadUrl }>Explore</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,13 @@ import StandaloneLayout from "./layout"
|
||||
import "../style/main.scss"
|
||||
|
||||
import TopbarPlugin from "plugins/topbar"
|
||||
import ConfigsPlugin from "plugins/configs"
|
||||
|
||||
// the Standalone preset
|
||||
|
||||
let preset = [
|
||||
TopbarPlugin,
|
||||
ConfigsPlugin,
|
||||
() => {
|
||||
return {
|
||||
components: { StandaloneLayout }
|
||||
|
||||
@@ -502,6 +502,11 @@ body
|
||||
{
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.headerline
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.scheme-container
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
display: flex;
|
||||
|
||||
max-width: 300px;
|
||||
|
||||
text-decoration: none;
|
||||
|
||||
flex: 1;
|
||||
@@ -33,8 +35,11 @@
|
||||
{
|
||||
display: flex;
|
||||
|
||||
flex: 3;
|
||||
|
||||
input[type=text]
|
||||
{
|
||||
width: 100%;
|
||||
min-width: 350px;
|
||||
margin: 0;
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
README.md
|
||||
deploy.sh
|
||||
@@ -0,0 +1 @@
|
||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||
@@ -0,0 +1,3 @@
|
||||
This module, `swagger-ui-dist`, exposes Swagger-UI's entire dist folder as a dependency-free npm module.
|
||||
|
||||
Use `swagger-ui` instead, if you'd like to have npm install dependencies for you.
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
# Deploy `swagger-ui-dist` to npm.
|
||||
|
||||
# Parameter Expansion: http://stackoverflow.com/questions/6393551/what-is-the-meaning-of-0-in-a-bash-script
|
||||
cd "${0%/*}"
|
||||
|
||||
# Get UI version
|
||||
UI_VERSION=$(node -p "require('../package.json').version")
|
||||
|
||||
# Replace our version placeholder with UI's version
|
||||
sed -i "s|\$\$VERSION|$UI_VERSION|g" package.json
|
||||
|
||||
# Copy UI's dist files to our directory
|
||||
cp ../dist/* .
|
||||
|
||||
if [ "$PUBLISH_DIST" = "true" ] || [ "$TRAVIS" = "true" ] ; then
|
||||
npm publish .
|
||||
else
|
||||
npm pack .
|
||||
fi
|
||||
|
||||
find . -not -name .npmignore -not -name .npmrc -not -name deploy.sh -not -name package.json -not -name README.md -not -name *.tgz -delete
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "swagger-ui-dist",
|
||||
"version": "$$VERSION",
|
||||
"main": "dist/swagger-ui.js",
|
||||
"repository": "git@github.com:swagger-api/swagger-ui.git",
|
||||
"contributors": [
|
||||
"(in alphabetical order)",
|
||||
"Anna Bodnia <anna.bodnia@gmail.com>",
|
||||
"Buu Nguyen <buunguyen@gmail.com>",
|
||||
"Josh Ponelat <jponelat@gmail.com>",
|
||||
"Kyle Shockey <kyleshockey1@gmail.com>",
|
||||
"Robert Barnwell <robert@robertismy.name>",
|
||||
"Sahar Jafari <shr.jafari@gmail.com>"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {},
|
||||
"devDependencies": {}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/* eslint-env mocha */
|
||||
import expect from "expect"
|
||||
import { fromJS } from "immutable"
|
||||
import reducer from "corePlugins/spec/reducers"
|
||||
|
||||
describe("spec plugin - reducer", function(){
|
||||
|
||||
describe("update operation value", function() {
|
||||
it("should update the operation at the specified key", () => {
|
||||
const updateOperationValue = reducer["spec_update_operation_value"]
|
||||
|
||||
const state = fromJS({
|
||||
resolved: {
|
||||
"paths": {
|
||||
"/pet": {
|
||||
"post": {
|
||||
"description": "my operation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let result = updateOperationValue(state, {
|
||||
payload: {
|
||||
path: ["/pet", "post"],
|
||||
value: "application/json",
|
||||
key: "consumes_value"
|
||||
}
|
||||
})
|
||||
|
||||
let expectedResult = {
|
||||
resolved: {
|
||||
"paths": {
|
||||
"/pet": {
|
||||
"post": {
|
||||
"description": "my operation",
|
||||
"consumes_value": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect(result.toJS()).toEqual(expectedResult)
|
||||
})
|
||||
|
||||
it("shouldn't throw an error if we try to update the consumes_value of a null operation", () => {
|
||||
const updateOperationValue = reducer["spec_update_operation_value"]
|
||||
|
||||
const state = fromJS({
|
||||
resolved: {
|
||||
"paths": {
|
||||
"/pet": {
|
||||
"post": null
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let result = updateOperationValue(state, {
|
||||
payload: {
|
||||
path: ["/pet", "post"],
|
||||
value: "application/json",
|
||||
key: "consumes_value"
|
||||
}
|
||||
})
|
||||
|
||||
expect(result.toJS()).toEqual(state.toJS())
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -22,7 +22,10 @@ module.exports = require('./make-webpack-config.js')({
|
||||
},
|
||||
|
||||
externals: function(context, request, cb) {
|
||||
if(node_modules.indexOf(request) !== -1) {
|
||||
// webpack injects some stuff into the resulting file,
|
||||
// these libs need to be pulled in to keep that working.
|
||||
var exceptionsForWebpack = ["ieee754", "base64-js"]
|
||||
if(node_modules.indexOf(request) !== -1 || exceptionsForWebpack.indexOf(request) !== -1) {
|
||||
cb(null, 'commonjs ' + request)
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user