Compare commits

...
120 Commits
Author SHA1 Message Date
kyle e7b3fd3efb Merge pull request #3866 from swagger-api/v/3.4.3
v3.4.3
2017-11-03 19:53:12 -07:00
Kyle Shockey 4a76e6f2cd v3.4.3 2017-11-03 19:48:30 -07:00
kyle 500c10bbc2 Merge pull request #3865 from swagger-api/xml-2-spaces
Indent XML with 2 spaces
2017-11-03 18:19:26 -07:00
Kyle Shockey d5d7e45d62 Indent XML with 2 spaces 2017-11-03 18:13:17 -07:00
kyle 261b73bd0f Merge pull request #3839 from heldersepu/bug/validation-messages
Fix issue with the error messages
2017-11-03 17:23:44 -07:00
kyle 4315cf6b94 Merge branch 'master' into bug/validation-messages 2017-11-03 17:17:21 -07:00
kyle b3e86b3f76 Merge pull request #3798 from swagger-api/swagger-ui/master
Add validatePattern
2017-11-03 17:16:38 -07:00
kyle b584837f42 Merge branch 'master' into master 2017-11-03 17:12:35 -07:00
Kyle Shockey 390f4b17b1 Add graceful failure test 2017-11-03 17:11:39 -07:00
kyle 53ca59ee5e Merge pull request #3807 from swagger-api/swagger-ui/execute-animation-cpu-usage
Reduce high cpu/gpu usage of 'Execute' btn animation
2017-11-03 16:15:48 -07:00
kyle c3123224d3 Merge branch 'master' into execute-animation-cpu-usage 2017-11-03 16:11:30 -07:00
kyle 5ec2d8d1bf Merge pull request #3845 from swagger-api/travis-performance
Travis performance
2017-11-03 15:00:33 -07:00
kyle 6fa7b92cad Update .travis.yml 2017-11-03 14:56:08 -07:00
kyle 1a15974778 Merge branch 'master' into travis-performance 2017-11-03 14:55:24 -07:00
kyle 9994996ba9 Merge pull request #3815 from swagger-api/swagger-ui/feature/add-oas3-wrapper-for-specSelectors-hasHost
add specSelectors.hasHost for OAS3
2017-11-03 14:25:55 -07:00
Josh Ponelat 44361d1cbb add specSelectors.hasHost for OAS3 2017-11-03 17:58:15 +02:00
kyle 67c925c1bd Merge pull request #3861 from thompsongl/ft/property-component
Add Property display component
2017-11-02 18:01:21 -07:00
kyle 09b37428c2 Merge branch 'master' into ft/property-component 2017-11-02 17:51:59 -07:00
kyle a6bb7f1dd8 Merge pull request #3769 from casions/ft/convert-scss-colors-into-variables
Replace color values with variables for easier theming
2017-11-02 17:14:09 -07:00
kyle 588cacba39 Merge branch 'master' into ft/convert-scss-colors-into-variables 2017-11-02 17:09:17 -07:00
kyle 8e0f519ad3 Merge pull request #3844 from hkosova/bearer-dialog-fix
Removed redundant "In:" label from Bearer auth dialog
2017-11-02 17:05:19 -07:00
kyle c50abd8cc9 Merge branch 'master' into bearer-dialog-fix 2017-11-02 16:58:36 -07:00
kyle 1e44f6253f Merge pull request #3813 from swagger-api/feature/configsPlugin
Refactor configs plugin, using state
2017-11-02 16:57:36 -07:00
kyle 466158af08 Merge branch 'master' into feature/configsPlugin 2017-11-02 16:53:21 -07:00
kyle be34c8d7fc Merge pull request #3862 from swagger-api/bug/3858-xml-formatting-perf
XML response body formatting performance
2017-11-02 15:30:42 -07:00
kyle dbc154b330 Merge branch 'master' into bug/3858-xml-formatting-perf 2017-11-02 15:23:11 -07:00
Kyle Shockey 17e6d81504 Format XML with xml-but-prettier 2017-11-02 15:13:10 -07:00
Greg Thompson 4b453e3535 use property component in array-model and primitive-model 2017-11-02 15:20:20 -05:00
Greg Thompson 0c41155100 adds new property display component 2017-11-02 15:19:38 -05:00
kyle d19646f484 Merge pull request #3805 from gilbode/ft/react_15_6_2
Upgrade to react 15.6.2.
2017-11-02 10:35:00 -07:00
kyle 00105924b5 Merge branch 'master' into ft/react_15_6_2 2017-11-02 09:37:42 -07:00
Stuart Nichols 1a02364c2f Replace color values with variables for easier theming
Replaced all color values with variables in scss files and
added associated variables to _variables.scss file
2017-11-02 11:50:33 +00:00
kyle a95f138da7 Merge branch 'master' into feature/configsPlugin 2017-11-01 20:56:58 -07:00
Kyle Shockey 9914b1dca6 Revert "build"
This reverts commit 9058668889.
2017-11-01 20:54:31 -07:00
HelderSepu 034ebb021c Remove redundant Boolean call 2017-11-01 22:00:39 -04:00
Helder Sepulveda 070bed00df Merge branch 'master' into bug/slow-formatXml 2017-11-01 21:55:15 -04:00
Helder Sepulveda 7fd1a03c1d Merge branch 'master' into bug/slow-formatXml 2017-11-01 21:52:45 -04:00
HelderSepu f600fe8dbb Simplify formatXml 2017-11-01 21:48:18 -04:00
kyle 9eae562767 Merge pull request #3854 from swagger-api/swagger-ui/versions-doc-fix
Made it clearer how to get version from browser console
2017-11-01 18:31:27 -07:00
Helder Sepulveda 87bbb9eb9f Merge branch 'master' into bug/validation-messages 2017-11-01 09:33:00 -04:00
Helder Sepulveda d73715f1fa Merge branch 'master' into master 2017-11-01 09:32:49 -04:00
Robin Björklin a6b574deae Made it clearer how to get version from browser console 2017-11-01 07:35:35 +01:00
kyle 1d98a8f4d1 Merge pull request #3852 from swagger-api/bug/3851-validatorurl-sanitization-type
Check for input type and string length before sanitizing a URL
2017-10-31 12:45:13 -07:00
kyle cea30ff7f8 Merge branch 'master' into bug/3851-validatorurl-sanitization-type 2017-10-31 12:40:30 -07:00
Kyle Shockey 1aa1907128 Check for input type and string length before sanitizing a URL 2017-10-31 12:35:08 -07:00
kyle 09f1f2595f Add security notice to issue template 2017-10-30 18:52:21 -07:00
kyle 164747d407 Merge pull request #3849 from swagger-api/v/3.4.2
v3.4.2
2017-10-30 18:48:20 -07:00
Kyle Shockey 1c13649d02 v3.4.2 2017-10-30 18:45:37 -07:00
kyle 2b25e655ca Merge pull request #3848 from swagger-api/bug/3847-href-xss
Add URL sanitizer to avoid `href` XSS attack vector
2017-10-30 18:12:50 -07:00
Kyle Shockey 551a82d120 Remove describe.only 2017-10-30 18:00:59 -07:00
Kyle Shockey b9fa5e5bb2 Add sanitizeUrl tests 2017-10-30 17:57:43 -07:00
Kyle Shockey afa615e01d Add URL sanitizer to avoid javascript: XSS attack vector 2017-10-30 17:43:23 -07:00
Kyle Shockey a0219051c3 Cache node_modules 2017-10-30 13:16:59 -07:00
Helen Kosova 73371b4f9c Removed redundant "In:" label from Bearer auth dialog 2017-10-30 21:01:40 +03:00
HelderSepu ec2179f019 Fix issue with the error messages
Many of the errors where incorrectly showing "Required field is not
provided" when the field was provided but not valid.
This was raised by @ron on PR #3825
2017-10-28 16:21:40 -04:00
Helder Sepulveda 9840abeccc Merge branch 'master' into master 2017-10-28 11:56:56 -04:00
kyle 4eae9b681b Merge pull request #3835 from swagger-api/v/3.4.1
v3.4.1
2017-10-28 00:43:16 -07:00
Kyle Shockey bdc0435683 v3.4.1 2017-10-28 00:37:55 -07:00
kyle 3c371915af Merge pull request #3834 from swagger-api/bug/3818-definitions-to-authorize-cache-invalidation
memoize definitionsToAuthorize based on securityDefinitons value
2017-10-28 00:03:14 -07:00
kyle ba6e8d14a3 Merge branch 'master' into bug/3818-definitions-to-authorize-cache-invalidation 2017-10-27 23:55:25 -07:00
kyle b90a4d3c71 Merge pull request #3833 from swagger-api/bug/3811-oas3-enum-execute
Pass correct schema values to parameter state builder for OAS3
2017-10-27 23:55:17 -07:00
Kyle Shockey 2157988212 Don't reach into schema for value 2017-10-27 23:31:47 -07:00
Kyle Shockey 109f7ed430 memoize definitionsToAuthorize based on securityDefinitons value 2017-10-27 22:41:27 -07:00
Kyle Shockey 79ddae1526 Pass correct schema values to parameter state builder for OAS3 2017-10-27 22:23:11 -07:00
kyle ac36d46467 Merge pull request #3829 from swagger-api/pull-request-template
Create pull request template
2017-10-27 13:01:14 -07:00
Helder Sepulveda 509037c6c0 Merge branch 'master' into master 2017-10-27 15:53:23 -04:00
kyle b3a8e4d380 Merge branch 'master' into pull-request-template 2017-10-27 12:44:23 -07:00
kyle c33a37d8db Merge pull request #3831 from swagger-api/bug/3816-oas3-authorize-always-showing
Return null instead of empty ImmutableMap in OAS3 securityDefinitions selector
2017-10-26 15:55:32 -07:00
kyle 2caca555b1 Merge branch 'master' into bug/3816-oas3-authorize-always-showing 2017-10-26 15:49:05 -07:00
Kyle Shockey 7159649501 Return null instead of empty ImmutableMap in OAS3 securityDefinitions selector 2017-10-26 15:32:14 -07:00
kyle 3e7a0764bb Merge pull request #3830 from swagger-api/bug/resolver-interception
Provide interceptors to SwaggerClient.resolve
2017-10-26 15:06:32 -07:00
kyle 35f1e94c04 Merge branch 'master' into bug/resolver-interception 2017-10-26 14:58:56 -07:00
Kyle Shockey 26428cd63b Provide interceptors to SwaggerClient.resolve 2017-10-26 14:51:00 -07:00
kyle 896e160e2b Improve spacing and section header sizes 2017-10-26 12:08:52 -07:00
kyle 565318739c Add no code changes and dependency changes 2017-10-26 12:02:06 -07:00
kyle f5217f9c99 Merge pull request #3828 from swagger-api/shockey-patch-1
Improve UX
2017-10-26 11:59:09 -07:00
kyle cb9804b5ca Create pull_request_template.md 2017-10-26 11:58:54 -07:00
kyle 8f0b498374 Update add-plugin.md 2017-10-26 10:59:06 -07:00
kyle 71c33d0af8 Update topbar.jsx 2017-10-26 10:57:36 -07:00
Josh Ponelat 9058668889 build 2017-10-25 10:03:59 +02:00
Josh Ponelat 50b318c5d9 Create a configs plugin
This starts to migrate configs to state
2017-10-25 09:59:54 +02:00
HelderSepu 43c5d9a8c9 Revert "Add objectCheck"
This reverts commit 87d11f99dd.
2017-10-24 18:35:28 -04:00
HelderSepu 87d11f99dd Add objectCheck
Squeeze fix for required object on this PR
2017-10-24 17:49:56 -04:00
Ron c2bdb3af24 Merge pull request #3810 from iiska/relative-json-path
Fix accessing bundled swagger json behind reverse proxy
2017-10-24 09:58:25 -07:00
Juhamatti Niemelä 6dd5d80770 Fix accessing bundled swagger json behind reverse proxy
If swagger-ui is run behind reverse proxy in path other than / accessing
bundled swagger json configured in SWAGGER_JSON env variable will fail.

Fix that by changing REL_PATH prefix from `/` to `./`
2017-10-24 16:42:51 +03:00
sserbin cb274caa1f hinting browser about 'Execute' button animation
in attempt to decrease ridiculously high cpu usage of swagger-ui-pulse animation
2017-10-24 01:55:40 +03:00
Mike Gilbode a07b276d23 Upgrade to react 15.6.2. 2017-10-23 15:02:41 -04:00
Helder Sepulveda 12d5132ed3 Merge branch 'master' into master 2017-10-23 09:56:12 -04:00
kyle 96b0b04538 Merge pull request #3799 from swagger-api/bug/mocha-exclusive-tests
Add ESLint rule that catches `describe.only`, `it.only`
2017-10-21 12:25:36 -07:00
Kyle Shockey 075c94f68c Remove describe.only 2017-10-21 11:13:01 -07:00
Kyle Shockey fc11f7a556 Add ESLint rule that catches describe.only, it.only 2017-10-21 11:11:13 -07:00
HelderSepu efa468bac5 remove semicolon 2017-10-21 13:20:48 -04:00
HelderSepu ac24f4376b Add validatePattern & UnitTest 2017-10-21 13:04:53 -04:00
HelderSepu 21178e9107 Remove describe.only 2017-10-21 13:04:21 -04:00
kyle c4a74d4db7 Merge pull request #3797 from swagger-api/v/3.4.0
v3.4.0
2017-10-20 20:37:07 -07:00
Kyle Shockey d6b9ace648 v3.4.0 2017-10-20 20:30:13 -07:00
kyle c46e18deeb Merge pull request #3780 from swagger-api/ft/oas3-authorization
OAS 3.0 Authorization
2017-10-20 19:45:24 -07:00
Kyle Shockey 7c917325f0 Linter fixes 2017-10-20 19:31:52 -07:00
kyle 6d22e38a04 Merge branch 'master' into ft/oas3-authorization 2017-10-20 19:07:38 -07:00
kyle 353fd00b08 Merge pull request #3746 from racedale/master
Support for mobile view on Swagger UI
2017-10-20 18:12:51 -07:00
kyle bc676601a8 Merge branch 'master' into master 2017-10-20 16:59:19 -07:00
kyle 3387d4762f Merge pull request #3796 from swagger-api/bug/editor-1530-array-parameter-input
Pass `parameter.schema` as schema in OAS 3.0
2017-10-20 16:58:04 -07:00
Ron d953b7790d Merge branch 'master' into master 2017-10-20 16:54:03 -07:00
Kyle Shockey 631e69f6f8 Pass parameter.schema as schema in OAS 3.0
Parameters were restructured in OAS 3.0; schemas are no longer at
the top level of parameters. Adjusting to account for the change.
2017-10-20 16:01:26 -07:00
kyle 9a442b16e3 Merge pull request #3793 from swagger-api/ft/sourcemaps
Sourcemaps
2017-10-20 14:21:11 -07:00
kyle 4ac3212341 Merge branch 'master' into ft/sourcemaps 2017-10-19 23:06:04 -07:00
Kyle Shockey e51d6c2ed5 Stop babelifying dev server twice; use eval-source-map 2017-10-19 22:48:34 -07:00
Kyle Shockey dccc9cfc36 Switch to nosource-source-map for dist builds 2017-10-19 22:47:44 -07:00
Owen Conti 53a4af6885 Merge pull request #3790 from owenconti/bug/3783-response-description-styles
Fixes #3783
2017-10-19 16:27:54 -06:00
Owen Conti 95002ba6e5 Fixes #3783
Remove extra styles for .renderedMarkdown content.
2017-10-19 14:44:17 -06:00
Kyle Shockey c9674a1fc5 Refactor Auths component flow; create component that supports HTTP auths 2017-10-18 21:23:28 -07:00
kyle e184762b0f Merge pull request #3768 from mhw/fix-markdown-links
Fix regression with rendering links in Markdown.
2017-10-16 14:15:23 -07:00
Mark H. Wilkinson e1a7af4c92 Fix regression with rendering links in Markdown. 2017-10-16 14:40:07 +01:00
Kyle Shockey d677e534c3 WIP 2017-10-13 21:23:45 -07:00
Kyle Shockey 8b81bcac48 OAS3 Auth MVP 2017-10-11 16:58:24 -07:00
Race, Dale 4da430c08e Lower select and input button width's on mobile 2017-10-11 09:12:55 -05:00
Race, Dale 499d61161a Decrease summary-path font size on mobile 2017-10-11 09:12:17 -05:00
Race, Dale 8acac155e1 Tweak padding values for topbar to fit mobile 2017-10-11 08:46:19 -05:00
Race, Dale 59188b1bfe Remove min-width from search url input field 2017-10-11 08:45:41 -05:00
Race, Dale 3711d19064 Add viewport meta tag 2017-10-11 08:43:02 -05:00
71 changed files with 1226 additions and 421 deletions
+4 -2
View File
@@ -16,7 +16,8 @@
"extends": ["eslint:recommended", "plugin:react/recommended"],
"plugins": [
"react"
"react",
"mocha"
],
"rules": {
@@ -32,6 +33,7 @@
"comma-dangle": 0,
"no-console": ["error", { allow: ["warn", "error"] }],
"react/jsx-no-bind": 1,
"react/display-name": 0
"react/display-name": 0,
"mocha/no-exclusive-tests": "error"
}
}
+3
View File
@@ -1,6 +1,9 @@
<!---
Thanks for filing an issue 😄 ! Before you submit, please read the following:
If you're here to report a security issue, please STOP writing an issue and contact us
at security@swagger.io instead!
Search open/closed issues before submitting since someone might have asked the same thing before!
Issues on GitHub are only related to problems of Swagger-UI itself. We'll try to offer support
+42
View File
@@ -0,0 +1,42 @@
<!--- Provide a general summary of your changes in the Title above -->
### Description
<!--- Describe your changes in detail -->
### Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
<!--- Use the magic "Fixes #1234" format, so the issues are -->
<!--- automatically closed when this PR is merged. -->
### How Has This Been Tested?
<!--- Please describe in detail how you manually tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
### Screenshots (if appropriate):
### Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] No code changes (changes to documentation, CI, metadata, etc)
- [ ] Dependency changes (any modification to dependencies in `package.json`)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
### Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed.
+4
View File
@@ -1,12 +1,16 @@
language: node_js
node_js:
- '6.9'
cache:
directories:
- node_modules
services:
- docker
branches:
only:
- master
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
install: "npm i && npm update"
before_deploy:
- npm run build
env:
+1 -1
View File
@@ -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.3.2 | 2017-10-13 | 2.0, 3.0 | [tag v3.3.2](https://github.com/swagger-api/swagger-ui/tree/v3.3.2)
3.4.3 | 2017-11-03 | 2.0, 3.0 | [tag v3.4.3](https://github.com/swagger-api/swagger-ui/tree/v3.4.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)
+1
View File
@@ -3,6 +3,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Swagger UI</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
+4 -1
View File
@@ -27,7 +27,10 @@
isValid = qp.state === sentState
if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) {
if ((
oauth2.auth.schema.get("flow") === "accessCode"||
oauth2.auth.schema.get("flow") === "authorizationCode"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
+4 -1
View File
@@ -27,7 +27,10 @@
isValid = qp.state === sentState
if (oauth2.auth.schema.get("flow") === "accessCode" && !oauth2.auth.code) {
if ((
oauth2.auth.schema.get("flow") === "accessCode"||
oauth2.auth.schema.get("flow") === "authorizationCode"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
+67 -29
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"swagger-ui.css","sources":[],"mappings":"","sourceRoot":""}
{"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""}
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -32,7 +32,7 @@ fi
if [[ -f $SWAGGER_JSON ]]; then
cp $SWAGGER_JSON $NGINX_ROOT
REL_PATH="/$(basename $SWAGGER_JSON)"
REL_PATH="./$(basename $SWAGGER_JSON)"
sed -i "s|http://petstore.swagger.io/v2/swagger.json|$REL_PATH|g" $INDEX_FILE
sed -i "s|http://example.com/api|$REL_PATH|g" $INDEX_FILE
else
+3 -3
View File
@@ -20,8 +20,8 @@ Some distinct identifiers to Swagger-UI 3.X:
If you've determined this is the version you have, to find the exact version:
- Open your browser's web console (changes between browsers)
- Type `versions` in the console and execute the call.
- You might need to expand the result, until you get a string similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`.
- Type `JSON.stringify(versions)` in the console and execute the call.
- The result should look similar to `swaggerUi : Object { version: "3.1.6", gitRevision: "g786cd47", gitDirty: true, … }`.
- The version taken from that example would be `3.1.6`.
Note: This functionality was added in 3.0.8. If you're unable to execute it, you're likely to use an older version, and in that case the first step would be to upgrade.
@@ -51,4 +51,4 @@ If you've determined this is the version you have, to find the exact version:
* @link http://swagger.io
* @license Apache-2.0
*/
```
```
+1 -1
View File
@@ -137,7 +137,7 @@ module.exports = function(rules, options) {
}
},
devtool: specialOptions.sourcemaps ? "cheap-module-source-map" : null,
devtool: specialOptions.sourcemaps ? "nosource-source-map" : null,
plugins,
+8 -5
View File
@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.3.2",
"version": "3.4.3",
"main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [
@@ -39,6 +39,7 @@
"e2e": "npm-run-all --parallel -r hot-server mock-api test-e2e"
},
"dependencies": {
"@braintree/sanitize-url": "^2.0.2",
"base64-js": "^1.2.0",
"brace": "0.7.0",
"classnames": "^2.2.5",
@@ -55,12 +56,12 @@
"memoizee": "0.4.1",
"promise-worker": "^1.1.1",
"prop-types": "^15.5.10",
"react": "^15.4.0",
"react": "^15.6.2",
"react-addons-perf": "^15.4.0",
"react-addons-shallow-compare": "0.14.8",
"react-addons-test-utils": "^15.4.0",
"react-addons-test-utils": "^15.6.2",
"react-collapse": "2.3.1",
"react-dom": "^15.4.0",
"react-dom": "^15.6.2",
"react-height": "^2.0.0",
"react-hot-loader": "1.3.1",
"react-immutable-proptypes": "2.1.0",
@@ -78,11 +79,12 @@
"scroll-to-element": "^2.0.0",
"serialize-error": "2.0.0",
"shallowequal": "0.2.2",
"swagger-client": "^3.2.2",
"swagger-client": "^3.3.2",
"url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1",
"xml": "1.0.1",
"xml-but-prettier": "^1.0.1",
"yaml-js": "0.2.0"
},
"devDependencies": {
@@ -105,6 +107,7 @@
"enzyme": "^2.7.1",
"eslint": "^4.1.1",
"eslint-plugin-import": "^2.6.0",
"eslint-plugin-mocha": "^4.11.0",
"eslint-plugin-react": "^7.1.0",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "0.11.2",
+4 -5
View File
@@ -24,24 +24,23 @@ export default class ArrayModel extends Component {
const Markdown = getComponent("Markdown")
const ModelCollapse = getComponent("ModelCollapse")
const Model = getComponent("Model")
const Property = getComponent("Property")
const titleEl = title &&
<span className="model-title">
<span className="model-title__text">{ title }</span>
</span>
/*
/*
Note: we set `name={null}` in <Model> below because we don't want
the name of the current Model passed (and displayed) as the name of the array element Model
*/
*/
return <span className="model">
<ModelCollapse title={titleEl} collapsed={ depth > expandDepth } collapsedContent="[...]">
[
{
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }>
<br />{ key }: { String(v) }</span>)
: null
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
}
{
!description ? null :
+5 -4
View File
@@ -51,14 +51,15 @@ export default class ApiKeyAuth extends React.Component {
return (
<div>
<h4>Api key authorization<JumpToPath path={[ "securityDefinitions", name ]} /></h4>
<h4>
<code>{ name || schema.get("name") }</code>&nbsp;
(apiKey)
<JumpToPath path={[ "securityDefinitions", name ]} />
</h4>
{ value && <h6>Authorized</h6>}
<Row>
<Markdown source={ schema.get("description") } />
</Row>
<Row>
<p>Name: <code>{ schema.get("name") }</code></p>
</Row>
<Row>
<p>In: <code>{ schema.get("in") }</code></p>
</Row>
+62
View File
@@ -0,0 +1,62 @@
import React from "react"
import PropTypes from "prop-types"
import ImPropTypes from "react-immutable-proptypes"
export default class Auths extends React.Component {
static propTypes = {
schema: ImPropTypes.orderedMap.isRequired,
name: PropTypes.string.isRequired,
onAuthChange: PropTypes.func.isRequired,
authorized: ImPropTypes.orderedMap.isRequired
}
render() {
let {
schema,
name,
getComponent,
onAuthChange,
authorized,
errSelectors
} = this.props
const ApiKeyAuth = getComponent("apiKeyAuth")
const BasicAuth = getComponent("basicAuth")
let authEl
const type = schema.get("type")
switch(type) {
case "apiKey": authEl = <ApiKeyAuth key={ name }
schema={ schema }
name={ name }
errSelectors={ errSelectors }
authorized={ authorized }
getComponent={ getComponent }
onChange={ onAuthChange } />
break
case "basic": authEl = <BasicAuth key={ name }
schema={ schema }
name={ name }
errSelectors={ errSelectors }
authorized={ authorized }
getComponent={ getComponent }
onChange={ onAuthChange } />
break
default: authEl = <div key={ name }>Unknown security definition type { type }</div>
}
return (<div key={`${name}-jump`}>
{ authEl }
</div>)
}
static propTypes = {
errSelectors: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
authSelectors: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired,
definitions: ImPropTypes.iterable.isRequired
}
}
+10 -30
View File
@@ -27,7 +27,6 @@ export default class Auths extends React.Component {
e.preventDefault()
let { authActions } = this.props
authActions.authorize(this.state)
}
@@ -44,8 +43,7 @@ export default class Auths extends React.Component {
render() {
let { definitions, getComponent, authSelectors, errSelectors } = this.props
const ApiKeyAuth = getComponent("apiKeyAuth")
const BasicAuth = getComponent("basicAuth")
const AuthItem = getComponent("AuthItem")
const Oauth2 = getComponent("oauth2", true)
const Button = getComponent("Button")
@@ -64,33 +62,15 @@ export default class Auths extends React.Component {
!!nonOauthDefinitions.size && <form onSubmit={ this.submitAuth }>
{
nonOauthDefinitions.map( (schema, name) => {
let type = schema.get("type")
let authEl
switch(type) {
case "apiKey": authEl = <ApiKeyAuth key={ name }
schema={ schema }
name={ name }
errSelectors={ errSelectors }
authorized={ authorized }
getComponent={ getComponent }
onChange={ this.onAuthChange } />
break
case "basic": authEl = <BasicAuth key={ name }
schema={ schema }
name={ name }
errSelectors={ errSelectors }
authorized={ authorized }
getComponent={ getComponent }
onChange={ this.onAuthChange } />
break
default: authEl = <div key={ name }>Unknown security definition type { type }</div>
}
return (<div key={`${name}-jump`}>
{ authEl }
</div>)
return <AuthItem
key={name}
schema={schema}
name={name}
getComponent={getComponent}
onAuthChange={this.onAuthChange}
authorized={authorized}
errSelectors={errSelectors}
/>
}).toArray()
}
<div className="auth-btn-wrapper">
+13 -7
View File
@@ -2,11 +2,6 @@ import React from "react"
import PropTypes from "prop-types"
import oauth2Authorize from "core/oauth2-authorize"
const IMPLICIT = "implicit"
const ACCESS_CODE = "accessCode"
const PASSWORD = "password"
const APPLICATION = "application"
export default class Oauth2 extends React.Component {
static propTypes = {
name: PropTypes.string,
@@ -16,6 +11,7 @@ export default class Oauth2 extends React.Component {
authSelectors: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired,
errSelectors: PropTypes.object.isRequired,
specSelectors: PropTypes.object.isRequired,
errActions: PropTypes.object.isRequired,
getConfigs: PropTypes.any
}
@@ -83,7 +79,9 @@ export default class Oauth2 extends React.Component {
}
render() {
let { schema, getComponent, authSelectors, errSelectors, name } = this.props
let {
schema, getComponent, authSelectors, errSelectors, name, specSelectors
} = this.props
const Input = getComponent("Input")
const Row = getComponent("Row")
const Col = getComponent("Col")
@@ -92,6 +90,14 @@ export default class Oauth2 extends React.Component {
const JumpToPath = getComponent("JumpToPath", true)
const Markdown = getComponent( "Markdown" )
const { isOAS3 } = specSelectors
// Auth type consts
const IMPLICIT = "implicit"
const PASSWORD = "password"
const ACCESS_CODE = isOAS3() ? "authorizationCode" : "accessCode"
const APPLICATION = isOAS3() ? "clientCredentials" : "application"
let flow = schema.get("flow")
let scopes = schema.get("allowedScopes") || schema.get("scopes")
let authorizedAuth = authSelectors.authorized().get(name)
@@ -102,7 +108,7 @@ export default class Oauth2 extends React.Component {
return (
<div>
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
<h4>{name} (OAuth2, { schema.get("flow") }) <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
{ !this.state.appName ? null : <h5>Application: { this.state.appName } </h5> }
{ description && <Markdown source={ schema.get("description") } /> }
+7 -6
View File
@@ -2,6 +2,7 @@ import React from "react"
import PropTypes from "prop-types"
import { fromJS } from "immutable"
import ImPropTypes from "react-immutable-proptypes"
import { sanitizeUrl } from "core/utils"
class Path extends React.Component {
@@ -35,9 +36,9 @@ class Contact extends React.Component {
return (
<div>
{ url && <div><a href={ url } target="_blank">{ name } - Website</a></div> }
{ url && <div><a href={ sanitizeUrl(url) } target="_blank">{ name } - Website</a></div> }
{ email &&
<a href={`mailto:${email}`}>
<a href={sanitizeUrl(`mailto:${email}`)}>
{ url ? `Send email to ${name}` : `Contact ${name}`}
</a>
}
@@ -59,7 +60,7 @@ class License extends React.Component {
return (
<div>
{
url ? <a target="_blank" href={ url }>{ name }</a>
url ? <a target="_blank" href={ sanitizeUrl(url) }>{ name }</a>
: <span>{ name }</span>
}
</div>
@@ -97,7 +98,7 @@ export default class Info extends React.Component {
{ version && <VersionStamp version={version}></VersionStamp> }
</h2>
{ host || basePath ? <Path host={ host } basePath={ basePath } /> : null }
{ url && <a target="_blank" href={ url }><span className="url"> { url } </span></a> }
{ url && <a target="_blank" href={ sanitizeUrl(url) }><span className="url"> { url } </span></a> }
</hgroup>
<div className="description">
@@ -106,14 +107,14 @@ export default class Info extends React.Component {
{
termsOfService && <div>
<a target="_blank" href={ termsOfService }>Terms of service</a>
<a target="_blank" href={ sanitizeUrl(termsOfService) }>Terms of service</a>
</div>
}
{ contact && contact.size ? <Contact data={ contact } /> : null }
{ license && license.size ? <License license={ license } /> : null }
{ externalDocsUrl ?
<a target="_blank" href={externalDocsUrl}>{externalDocsDescription || externalDocsUrl}</a>
<a target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</a>
: null }
</div>
@@ -1,5 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import { sanitizeUrl } from "core/utils"
export default class OnlineValidatorBadge extends React.Component {
static propTypes = {
@@ -32,6 +33,8 @@ export default class OnlineValidatorBadge extends React.Component {
let { getConfigs } = this.props
let { spec } = getConfigs()
let sanitizedValidatorUrl = sanitizeUrl(this.state.validatorUrl)
if ( typeof spec === "object" && Object.keys(spec).length) return null
if (!this.state.url || !this.state.validatorUrl || this.state.url.indexOf("localhost") >= 0
@@ -40,8 +43,8 @@ export default class OnlineValidatorBadge extends React.Component {
}
return (<span style={{ float: "right"}}>
<a target="_blank" href={`${ this.state.validatorUrl }/debug?url=${ this.state.url }`}>
<ValidatorImage src={`${ this.state.validatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
<a target="_blank" href={`${ sanitizedValidatorUrl }/debug?url=${ this.state.url }`}>
<ValidatorImage src={`${ sanitizedValidatorUrl }?url=${ this.state.url }`} alt="Online validator badge"/>
</a>
</span>)
}
+2 -1
View File
@@ -2,6 +2,7 @@ import React, { PureComponent } from "react"
import PropTypes from "prop-types"
import { getList } from "core/utils"
import * as CustomPropTypes from "core/proptypes"
import { sanitizeUrl } from "core/utils"
//import "less/opblock"
@@ -206,7 +207,7 @@ export default class Operation extends PureComponent {
<span className="opblock-external-docs__description">
<Markdown source={ externalDocs.get("description") } />
</span>
<a className="opblock-external-docs__link" href={ externalDocs.get("url") }>{ externalDocs.get("url") }</a>
<a className="opblock-external-docs__link" href={ sanitizeUrl(externalDocs.get("url")) }>{ externalDocs.get("url") }</a>
</div>
</div> : null
}
+2 -2
View File
@@ -1,7 +1,7 @@
import React from "react"
import PropTypes from "prop-types"
import { helpers } from "swagger-client"
import { createDeepLinkPath } from "core/utils"
import { createDeepLinkPath, sanitizeUrl } from "core/utils"
const { opId } = helpers
export default class Operations extends React.Component {
@@ -101,7 +101,7 @@ export default class Operations extends React.Component {
{ tagExternalDocsUrl ? ": " : null }
{ tagExternalDocsUrl ?
<a
href={tagExternalDocsUrl}
href={sanitizeUrl(tagExternalDocsUrl)}
onClick={(e) => e.stopPropagation()}
target={"_blank"}
>{tagExternalDocsUrl}</a> : null
+13 -2
View File
@@ -1,4 +1,5 @@
import React, { Component } from "react"
import { Map } from "immutable"
import PropTypes from "prop-types"
import win from "core/window"
@@ -29,11 +30,21 @@ export default class ParameterRow extends Component {
componentWillReceiveProps(props) {
let { specSelectors, pathMethod, param } = props
let { isOAS3 } = specSelectors
let example = param.get("example")
let defaultValue = param.get("default")
let parameter = specSelectors.getParameter(pathMethod, param.get("name"), param.get("in"))
let enumValue
if(isOAS3()) {
let schema = param.get("schema") || Map()
enumValue = schema.get("enum")
} else {
enumValue = parameter ? parameter.get("enum") : undefined
}
let paramValue = parameter ? parameter.get("value") : undefined
let enumValue = parameter ? parameter.get("enum") : undefined
let value
if ( paramValue !== undefined ) {
@@ -115,7 +126,7 @@ export default class ParameterRow extends Component {
required={ required }
description={param.get("description") ? `${param.get("name")} - ${param.get("description")}` : `${param.get("name")}`}
onChange={ this.onChangeWrapper }
schema={ param }/>
schema={ isOAS3 && isOAS3() ? param.get("schema") : param }/>
}
+3 -4
View File
@@ -28,6 +28,7 @@ export default class Primitive extends Component {
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 )
const Markdown = getComponent("Markdown")
const EnumModel = getComponent("EnumModel")
const Property = getComponent("Property")
return <span className="model">
<span className="prop">
@@ -35,9 +36,7 @@ export default class Primitive extends Component {
<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
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <Property key={`${key}-${v}`} propKey={ key } propVal={ v } propStyle={ propStyle } />) : null
}
{
!description ? null :
@@ -56,4 +55,4 @@ export default class Primitive extends Component {
</span>
</span>
}
}
}
+16
View File
@@ -0,0 +1,16 @@
import React from "react"
import PropTypes from "prop-types"
export const Property = ({ propKey, propVal, propStyle }) => {
return (
<span style={ propStyle }>
<br />{ propKey }: { String(propVal) }</span>
)
}
Property.propTypes = {
propKey: PropTypes.string,
propVal: PropTypes.any,
propStyle: PropTypes.object
}
export default Property
@@ -31,6 +31,7 @@ export default Markdown
const sanitizeOptions = {
allowedTags: sanitize.defaults.allowedTags.concat([ "h1", "h2", "img" ]),
allowedAttributes: {
...sanitize.defaults.allowedAttributes,
"img": sanitize.defaults.allowedAttributes.img.concat(["title"])
},
textFilter: function(text) {
+5 -2
View File
@@ -1,6 +1,6 @@
import React from "react"
import PropTypes from "prop-types"
import { formatXml } from "core/utils"
import formatXml from "xml-but-prettier"
import lowerCase from "lodash/lowerCase"
export default class ResponseBody extends React.Component {
@@ -31,7 +31,10 @@ export default class ResponseBody extends React.Component {
// XML
} else if (/xml/i.test(contentType)) {
body = formatXml(content)
body = formatXml(content, {
textNodesOnSameLine: true,
indentor: " "
})
bodyEl = <HighlightCode value={ body } />
// HTML or Plain Text
+7 -8
View File
@@ -58,13 +58,12 @@ module.exports = function SwaggerUI(opts) {
plugins: [
],
// Initial state
initialState: { },
// Inline Plugin
fn: { },
components: { },
state: { },
// Override some core configs... at your own risk
store: { },
}
let queryConfig = parseSearch()
@@ -74,12 +73,12 @@ module.exports = function SwaggerUI(opts) {
const constructorConfig = deepExtend({}, defaults, opts, queryConfig)
const storeConfigs = deepExtend({}, constructorConfig.store, {
const storeConfigs = {
system: {
configs: constructorConfig.configs
},
plugins: constructorConfig.presets,
state: {
state: deepExtend({
layout: {
layout: constructorConfig.layout,
filter: constructorConfig.filter
@@ -88,8 +87,8 @@ module.exports = function SwaggerUI(opts) {
spec: "",
url: constructorConfig.url
}
}
})
}, constructorConfig.initialState)
}
let inlinePlugin = ()=> {
return {
+10
View File
@@ -22,6 +22,16 @@ export default function authorize ( { auth, authActions, errActions, configs, au
case "implicit":
query.push("response_type=token")
break
case "clientCredentials":
// OAS3
authActions.authorizeApplication(auth)
return
case "authorizationCode":
// OAS3
query.push("response_type=code")
break
}
if (typeof clientId === "string") {
+1 -1
View File
@@ -22,7 +22,7 @@ export default {
securities.entrySeq().forEach( ([ key, security ]) => {
let type = security.getIn(["schema", "type"])
if ( type === "apiKey" ) {
if ( type === "apiKey" || type === "http" ) {
map = map.set(key, security)
} else if ( type === "basic" ) {
let username = security.getIn(["value", "username"])
@@ -1,29 +1,60 @@
import { createSelector } from "reselect"
import { List } from "immutable"
import { List, Map, fromJS } from "immutable"
import { isOAS3 as isOAS3Helper } from "../helpers"
// Helpers
const state = state => state
function onlyOAS3(selector) {
return (ori, system) => (state, ...args) => {
const spec = system.getSystem().specSelectors.specJson()
if(isOAS3Helper(spec)) {
return selector(...args)
return selector(system, ...args)
} else {
return ori(...args)
}
}
}
const nullSelector = createSelector(() => null)
export const definitionsToAuthorize = onlyOAS3(createSelector(
state,
({specSelectors}) => specSelectors.securityDefinitions(),
(system, definitions) => {
// Coerce our OpenAPI 3.0 definitions into monoflow definitions
// that look like Swagger2 definitions.
let list = List()
const OAS3NullSelector = onlyOAS3(nullSelector)
definitions.entrySeq().forEach( ([ defName, definition ]) => {
const type = definition.get("type")
// Hasta la vista, authorization!
export const shownDefinitions = OAS3NullSelector
export const definitionsToAuthorize = OAS3NullSelector
export const getDefinitionsByNames = OAS3NullSelector
export const authorized = onlyOAS3(() => List())
export const isAuthorized = OAS3NullSelector
export const getConfigs = OAS3NullSelector
if(type === "oauth2") {
definition.get("flows").entrySeq().forEach(([flowKey, flowVal]) => {
let translatedDef = fromJS({
flow: flowKey,
authorizationUrl: flowVal.get("authorizationUrl"),
tokenUrl: flowVal.get("tokenUrl"),
scopes: flowVal.get("scopes"),
type: definition.get("type")
})
list = list.push(new Map({
[defName]: translatedDef.filter((v) => {
// filter out unset values, sometimes `authorizationUrl`
// and `tokenUrl` come out as `undefined` in the data
return v !== undefined
})
}))
})
}
if(type === "http" || type === "apiKey") {
list = list.push(new Map({
[defName]: definition
}))
}
})
return list
}
))
@@ -0,0 +1,131 @@
import React from "react"
import PropTypes from "prop-types"
export default class HttpAuth extends React.Component {
static propTypes = {
authorized: PropTypes.object,
getComponent: PropTypes.func.isRequired,
errSelectors: PropTypes.object.isRequired,
schema: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
onChange: PropTypes.func
}
constructor(props, context) {
super(props, context)
let { name, schema } = this.props
let value = this.getValue()
this.state = {
name: name,
schema: schema,
value: value
}
}
getValue () {
let { name, authorized } = this.props
return authorized && authorized.getIn([name, "value"])
}
onChange =(e) => {
let { onChange } = this.props
let { value, name } = e.target
let newValue = this.state.value || {}
if(name) {
newValue[name] = value
} else {
newValue = value
}
this.setState({ value: newValue }, () => onChange(this.state))
}
render() {
let { schema, getComponent, errSelectors, name } = this.props
const Input = getComponent("Input")
const Row = getComponent("Row")
const Col = getComponent("Col")
const AuthError = getComponent("authError")
const Markdown = getComponent( "Markdown" )
const JumpToPath = getComponent("JumpToPath", true)
const scheme = schema.get("scheme")
let value = this.getValue()
let errors = errSelectors.allErrors().filter( err => err.get("authId") === name)
if(scheme === "basic") {
let username = value ? value.get("username") : null
return <div>
<h4>
<code>{ name || schema.get("name") }</code>&nbsp;
(http, Basic)
<JumpToPath path={[ "securityDefinitions", name ]} />
</h4>
{ username && <h6>Authorized</h6> }
<Row>
<Markdown source={ schema.get("description") } />
</Row>
<Row>
<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 ? <code> ****** </code>
: <Col><Input required="required"
autoComplete="new-password"
name="password"
type="password"
onChange={ this.onChange }/></Col>
}
</Row>
{
errors.valueSeq().map( (error, key) => {
return <AuthError error={ error }
key={ key }/>
} )
}
</div>
}
if(scheme === "bearer") {
return (
<div>
<h4>
<code>{ name || schema.get("name") }</code>&nbsp;
(http, Bearer)
<JumpToPath path={[ "securityDefinitions", name ]} />
</h4>
{ value && <h6>Authorized</h6>}
<Row>
<Markdown source={ schema.get("description") } />
</Row>
<Row>
<label>Value:</label>
{
value ? <code> ****** </code>
: <Col><Input type="text" onChange={ this.onChange }/></Col>
}
</Row>
{
errors.valueSeq().map( (error, key) => {
return <AuthError error={ error }
key={ key }/>
} )
}
</div>
)
}
return <div>
<em><b>{name}</b> HTTP authentication: unsupported or missing scheme</em>
</div>
}
}
@@ -3,9 +3,11 @@ import RequestBody from "./request-body"
import OperationLink from "./operation-link.jsx"
import Servers from "./servers"
import RequestBodyEditor from "./request-body-editor"
import HttpAuth from "./http-auth"
export default {
Callbacks,
HttpAuth,
RequestBody,
Servers,
RequestBodyEditor,
@@ -48,12 +48,20 @@ export const definitions = onlyOAS3(createSelector(
spec => spec.getIn(["components", "schemas"]) || Map()
))
export const hasHost = onlyOAS3((state) => {
return spec(state).hasIn(["servers", 0])
})
export const securityDefinitions = onlyOAS3(createSelector(
spec,
spec => spec.getIn(["components", "securitySchemes"]) || null
))
export const host = OAS3NullSelector
export const basePath = OAS3NullSelector
export const consumes = OAS3NullSelector
export const produces = OAS3NullSelector
export const schemes = OAS3NullSelector
export const securityDefinitions = OAS3NullSelector
// New selectors
@@ -0,0 +1,23 @@
import React from "react"
import { OAS3ComponentWrapFactory } from "../helpers"
export default OAS3ComponentWrapFactory(({ Ori, ...props }) => {
const {
schema, getComponent, errSelectors, authorized, onAuthChange, name
} = props
const HttpAuth = getComponent("HttpAuth")
const type = schema.get("type")
if(type === "http") {
return <HttpAuth key={ name }
schema={ schema }
name={ name }
errSelectors={ errSelectors }
authorized={ authorized }
getComponent={ getComponent }
onChange={ onAuthChange }/>
} else {
return <Ori {...props} />
}
})
@@ -1,4 +1,5 @@
import Markdown from "./markdown"
import AuthItem from "./auth-item"
import parameters from "./parameters"
import VersionStamp from "./version-stamp"
import OnlineValidatorBadge from "./online-validator-badge"
@@ -6,6 +7,7 @@ import Model from "./model"
export default {
Markdown,
AuthItem,
parameters,
VersionStamp,
model: Model,
+16 -4
View File
@@ -80,7 +80,12 @@ export const parseToJson = (str) => ({specActions, specSelectors, errActions}) =
}
export const resolveSpec = (json, url) => ({specActions, specSelectors, errActions, fn: { fetch, resolve, AST }, getConfigs}) => {
const { modelPropertyMacro, parameterMacro } = getConfigs()
const {
modelPropertyMacro,
parameterMacro,
requestInterceptor,
responseInterceptor
} = getConfigs()
if(typeof(json) === "undefined") {
json = specSelectors.specJson()
@@ -93,8 +98,15 @@ export const resolveSpec = (json, url) => ({specActions, specSelectors, errActio
let specStr = specSelectors.specStr()
return resolve({fetch, spec: json, baseDoc: url, modelPropertyMacro, parameterMacro })
.then( ({spec, errors}) => {
return resolve({
fetch,
spec: json,
baseDoc: url,
modelPropertyMacro,
parameterMacro,
requestInterceptor,
responseInterceptor
}).then( ({spec, errors}) => {
errActions.clear({
type: "thrown"
})
@@ -140,7 +152,7 @@ export function changeParam( path, paramName, paramIn, value, isXml ){
export const validateParams = ( payload, isOAS3 ) =>{
return {
type: VALIDATE_PARAMS,
payload:{
payload:{
pathMethod: payload,
isOAS3
}
+6
View File
@@ -10,6 +10,7 @@ import auth from "core/plugins/auth"
import util from "core/plugins/util"
import SplitPaneModePlugin from "core/plugins/split-pane-mode"
import downloadUrlPlugin from "core/plugins/download-url"
import configsPlugin from "plugins/configs"
import deepLinkingPlugin from "core/plugins/deep-linking"
import App from "core/components/app"
@@ -17,6 +18,7 @@ import AuthorizationPopup from "core/components/auth/authorization-popup"
import AuthorizeBtn from "core/components/auth/authorize-btn"
import AuthorizeOperationBtn from "core/components/auth/authorize-operation-btn"
import Auths from "core/components/auth/auths"
import AuthItem from "core/components/auth/auth-item"
import AuthError from "core/components/auth/error"
import ApiKeyAuth from "core/components/auth/api-key-auth"
import BasicAuth from "core/components/auth/basic-auth"
@@ -51,6 +53,7 @@ import EnumModel from "core/components/enum-model"
import ObjectModel from "core/components/object-model"
import ArrayModel from "core/components/array-model"
import PrimitiveModel from "core/components/primitive-model"
import Property from "core/components/property"
import TryItOutButton from "core/components/try-it-out-button"
import VersionStamp from "core/components/version-stamp"
@@ -70,6 +73,7 @@ export default function() {
authorizeBtn: AuthorizeBtn,
authorizeOperationBtn: AuthorizeOperationBtn,
auths: Auths,
AuthItem: AuthItem,
authError: AuthError,
oauth2: Oauth2,
apiKeyAuth: ApiKeyAuth,
@@ -104,6 +108,7 @@ export default function() {
ObjectModel,
ArrayModel,
PrimitiveModel,
Property,
TryItOutButton,
Markdown,
BaseLayout,
@@ -120,6 +125,7 @@ export default function() {
}
return [
configsPlugin,
util,
logs,
view,
+33 -88
View File
@@ -1,5 +1,5 @@
import Im from "immutable"
import { sanitizeUrl as braintreeSanitizeUrl } from "@braintree/sanitize-url"
import camelCase from "lodash/camelCase"
import upperFirst from "lodash/upperFirst"
import _memoize from "lodash/memoize"
@@ -155,83 +155,6 @@ export function getList(iterable, keys) {
return Im.List.isList(val) ? val : Im.List()
}
// Adapted from http://stackoverflow.com/a/2893259/454004
// Note: directly ported from CoffeeScript
export function formatXml (xml) {
var contexp, fn, formatted, indent, l, lastType, len, lines, ln, reg, transitions, wsexp
reg = /(>)(<)(\/*)/g
wsexp = /[ ]*(.*)[ ]+\n/g
contexp = /(<.+>)(.+\n)/g
xml = xml.replace(/\r\n/g, "\n").replace(reg, "$1\n$2$3").replace(wsexp, "$1\n").replace(contexp, "$1\n$2")
formatted = ""
lines = xml.split("\n")
indent = 0
lastType = "other"
transitions = {
"single->single": 0,
"single->closing": -1,
"single->opening": 0,
"single->other": 0,
"closing->single": 0,
"closing->closing": -1,
"closing->opening": 0,
"closing->other": 0,
"opening->single": 1,
"opening->closing": 0,
"opening->opening": 1,
"opening->other": 1,
"other->single": 0,
"other->closing": -1,
"other->opening": 0,
"other->other": 0
}
fn = function(ln) {
var fromTo, key, padding, type, types, value
types = {
single: Boolean(ln.match(/<.+\/>/)),
closing: Boolean(ln.match(/<\/.+>/)),
opening: Boolean(ln.match(/<[^!?].*>/))
}
type = ((function() {
var results
results = []
for (key in types) {
value = types[key]
if (value) {
results.push(key)
}
}
return results
})())[0]
type = type === void 0 ? "other" : type
fromTo = lastType + "->" + type
lastType = type
padding = ""
indent += transitions[fromTo]
padding = ((function() {
/* eslint-disable no-unused-vars */
var m, ref1, results, j
results = []
for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {
results.push(" ")
}
/* eslint-enable no-unused-vars */
return results
})()).join("")
if (fromTo === "opening->closing") {
formatted = formatted.substr(0, formatted.length - 1) + ln + "\n"
} else {
formatted += padding + ln + "\n"
}
}
for (l = 0, len = lines.length; l < len; l++) {
ln = lines[l]
fn(ln)
}
return formatted
}
/**
* Adapted from http://github.com/asvd/microlight
* @copyright 2016 asvd <heliosframework@gmail.com>
@@ -536,6 +459,13 @@ export const validateMinLength = (val, min) => {
}
}
export const validatePattern = (val, rxPattern) => {
var patt = new RegExp(rxPattern)
if (!patt.test(val)) {
return "Value must follow pattern " + rxPattern
}
}
// validation of parameters before execute
export const validateParam = (param, isXml, isOAS3 = false) => {
let errors = []
@@ -549,6 +479,8 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
let format = paramDetails.get("format")
let maxLength = paramDetails.get("maxLength")
let minLength = paramDetails.get("minLength")
let pattern = paramDetails.get("pattern")
/*
If the parameter is required OR the parameter has a value (meaning optional, but filled in)
@@ -556,15 +488,25 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
Only bother validating the parameter if the type was specified.
*/
if ( type && (required || value) ) {
// These checks should evaluate to true if the parameter's value is valid
let stringCheck = type === "string" && value && !validateString(value)
// These checks should evaluate to true if there is a parameter
let stringCheck = type === "string" && value
let arrayCheck = type === "array" && Array.isArray(value) && value.length
let listCheck = type === "array" && Im.List.isList(value) && value.count()
let fileCheck = type === "file" && value instanceof win.File
let booleanCheck = type === "boolean" && !validateBoolean(value)
let numberCheck = type === "number" && !validateNumber(value) // validateNumber returns undefined if the value is a number
let integerCheck = type === "integer" && !validateInteger(value) // validateInteger returns undefined if the value is an integer
let booleanCheck = type === "boolean" && (value || value === false)
let numberCheck = type === "number" && value
let integerCheck = type === "integer" && value
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) {
errors.push("Required field is not provided")
return errors
}
if (pattern) {
let err = validatePattern(value, pattern)
if (err) errors.push(err)
}
if (maxLength || maxLength === 0) {
let err = validateMaxLength(value, maxLength)
if (err) errors.push(err)
@@ -575,11 +517,6 @@ export const validateParam = (param, isXml, isOAS3 = false) => {
if (err) errors.push(err)
}
if ( required && !(stringCheck || arrayCheck || listCheck || fileCheck || booleanCheck || numberCheck || integerCheck) ) {
errors.push("Required field is not provided")
return errors
}
if (maximum || maximum === 0) {
let err = validateMaximum(value, maximum)
if (err) errors.push(err)
@@ -722,6 +659,14 @@ export const shallowEqualKeys = (a,b, keys) => {
})
}
export function sanitizeUrl(url) {
if(typeof url !== "string" || url === "") {
return ""
}
return braintreeSanitizeUrl(url)
}
export function getAcceptControllingResponse(responses) {
if(!Im.OrderedMap.isOrderedMap(responses)) {
// wrong type!
+1 -1
View File
@@ -1,6 +1,6 @@
# Add a plugin
### Swagger-UX relies on plugins for all the good stuff.
### Swagger-UI relies on plugins for all the good stuff.
Plugins allow you to add
- `statePlugins`
+20
View File
@@ -0,0 +1,20 @@
export const UPDATE_CONFIGS = "configs_update"
export const TOGGLE_CONFIGS = "configs_toggle"
// Update the configs, with a merge ( not deep )
export function update(configName, configValue) {
return {
type: UPDATE_CONFIGS,
payload: {
[configName]: configValue
},
}
}
// Toggle's the config, by name
export function toggle(configName) {
return {
type: TOGGLE_CONFIGS,
payload: configName,
}
}
+53 -43
View File
@@ -1,56 +1,66 @@
import YAML from "js-yaml"
import yamlConfig from "../../../swagger-config.yaml"
import * as actions from "./actions"
import * as selectors from "./selectors"
import reducers from "./reducers"
const parseYamlConfig = (yaml, system) => {
try {
return YAML.safeLoad(yaml)
} catch(e) {
if (system) {
system.errActions.newThrownErr( new Error(e) )
}
return {}
try {
return YAML.safeLoad(yaml)
} catch(e) {
if (system) {
system.errActions.newThrownErr( new Error(e) )
}
return {}
}
}
export default function configPlugin (toolbox) {
let { fn } = toolbox
const actions = {
downloadConfig: (url) => () => {
let {fetch} = fn
return fetch(url)
},
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => {
if (configUrl) {
return specActions.downloadConfig(configUrl).then(next, next)
}
function next(res) {
if (res instanceof Error || res.status >= 400) {
specActions.updateLoadingStatus("failedConfig")
specActions.updateLoadingStatus("failedConfig")
specActions.updateUrl("")
console.error(res.statusText + " " + configUrl)
cb(null)
} else {
cb(parseYamlConfig(res.text))
}
}
}
const specActions = {
downloadConfig: (url) => ({fn}) => {
let {fetch} = fn
return fetch(url)
},
getConfigByUrl: (configUrl, cb)=> ({ specActions }) => {
if (configUrl) {
return specActions.downloadConfig(configUrl).then(next, next)
}
const selectors = {
getLocalConfig: () => {
return parseYamlConfig(yamlConfig)
}
}
return {
statePlugins: {
spec: { actions, selectors }
}
function next(res) {
if (res instanceof Error || res.status >= 400) {
specActions.updateLoadingStatus("failedConfig")
specActions.updateLoadingStatus("failedConfig")
specActions.updateUrl("")
console.error(res.statusText + " " + configUrl)
cb(null)
} else {
cb(parseYamlConfig(res.text))
}
}
}
}
const specSelectors = {
getLocalConfig: () => {
return parseYamlConfig(yamlConfig)
}
}
export default function configsPlugin() {
return {
statePlugins: {
spec: {
actions: specActions,
selectors: specSelectors,
},
configs: {
reducers,
actions,
selectors,
}
}
}
}
+20
View File
@@ -0,0 +1,20 @@
import { fromJS } from "immutable"
import {
UPDATE_CONFIGS,
TOGGLE_CONFIGS,
} from "./actions"
export default {
[UPDATE_CONFIGS]: (state, action) => {
return state.merge(fromJS(action.payload))
},
[TOGGLE_CONFIGS]: (state, action) => {
const configName = action.payload
const oriVal = state.get(configName)
return state.set(configName, !oriVal)
},
}
+4
View File
@@ -0,0 +1,4 @@
// Just get the config value ( it can possibly be an immutable object)
export const get = (state, path) => {
return state.getIn(Array.isArray(path) ? path : [path])
}
+1 -1
View File
@@ -129,7 +129,7 @@ export default class Topbar extends React.Component {
<div className="topbar">
<div className="wrapper">
<div className="topbar-wrapper">
<Link href="#" title="Swagger UX">
<Link href="#">
<img height="30" width="30" src={ Logo } alt="Swagger UI"/>
<span>swagger</span>
</Link>
+1 -1
View File
@@ -25,7 +25,7 @@
margin: 0 0 10px 0;
padding: 10px 20px;
border-bottom: 1px solid #ebebeb;
border-bottom: 1px solid $auth-container-border-color;
&:last-of-type
{
+23 -24
View File
@@ -7,10 +7,10 @@
transition: all .3s;
border: 2px solid #888;
border: 2px solid $btn-border-color;
border-radius: 4px;
background: transparent;
box-shadow: 0 1px 2px rgba(#000,.1);
box-shadow: 0 1px 2px rgba($btn-box-shadow-color,.1);
@include text_headline();
@@ -29,14 +29,14 @@
&:hover
{
box-shadow: 0 0 5px rgba(#000,.3);
box-shadow: 0 0 5px rgba($btn-box-shadow-color,.3);
}
&.cancel
{
border-color: #ff6060;
@include text_headline(#ff6060);
border-color: $btn-cancel-border-color;
background-color: $btn-cancel-background-color;
@include text_headline($btn-cancel-font-color);
}
&.authorize
@@ -45,9 +45,9 @@
display: inline;
color: $_color-post;
border-color: $_color-post;
color: $btn-authorize-font-color;
border-color: $btn-authorize-border-color;
background-color: $btn-authorize-background-color;
span
{
@@ -58,16 +58,17 @@
svg
{
fill: $_color-post;
fill: $btn-authorize-svg-fill-color;
}
}
&.execute
{
animation: swagger-ui-pulse 2s infinite;
color: #fff;
border-color: #4990e2;
will-change: transform;
background-color: $btn-execute-background-color;
color: $btn-execute-font-color;
border-color: $btn-execute-border-color;
}
}
@@ -76,21 +77,19 @@
{
0%
{
color: #fff;
background: #4990e2;
box-shadow: 0 0 0 0 rgba(#4990e2, .8);
color: $btn-execute-font-color;
background: $btn-execute-background-color-alt;
box-shadow: 0 0 0 0 rgba($btn-execute-background-color-alt, .8);
}
70%
{
//color: #4990e2;
//background: transparent;
box-shadow: 0 0 0 5px rgba(#4990e2, 0);
box-shadow: 0 0 0 5px rgba($btn-execute-background-color-alt, 0);
}
100%
{
color: #fff;
background: #4990e2;
box-shadow: 0 0 0 0 rgba(#4990e2, 0);
color: $btn-execute-font-color;
background: $btn-execute-background-color-alt;
box-shadow: 0 0 0 0 rgba($btn-execute-background-color-alt, 0);
}
}
@@ -155,7 +154,7 @@
{
svg
{
fill: #444;
fill: $expand-methods-svg-fill-color-hover;
}
}
@@ -163,7 +162,7 @@
{
transition: all .3s;
fill: #777;
fill: $expand-methods-svg-fill-color;
}
}
+1 -1
View File
@@ -27,7 +27,7 @@
small
{
color: #666;
color: $errors-wrapper-errors-small-font-color;
}
}
+22 -14
View File
@@ -5,11 +5,11 @@ select
padding: 5px 40px 5px 10px;
border: 2px solid #41444e;
border: 2px solid $form-select-border-color;
border-radius: 4px;
background: #f7f7f7 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat;
background: $form-select-background-color url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+ICAgIDxwYXRoIGQ9Ik0xMy40MTggNy44NTljLjI3MS0uMjY4LjcwOS0uMjY4Ljk3OCAwIC4yNy4yNjguMjcyLjcwMSAwIC45NjlsLTMuOTA4IDMuODNjLS4yNy4yNjgtLjcwNy4yNjgtLjk3OSAwbC0zLjkwOC0zLjgzYy0uMjctLjI2Ny0uMjctLjcwMSAwLS45NjkuMjcxLS4yNjguNzA5LS4yNjguOTc4IDBMMTAgMTFsMy40MTgtMy4xNDF6Ii8+PC9zdmc+) right 10px center no-repeat;
background-size: 20px;
box-shadow: 0 1px 2px 0 rgba(0,0,0,.25);
box-shadow: 0 1px 2px 0 rgba($form-select-box-shadow-color, .25);
@include text_headline();
appearance: none;
@@ -19,7 +19,7 @@ select
margin: 5px 0;
padding: 5px;
background: #f7f7f7;
background: $form-select-background-color;
}
&.invalid {
@@ -30,6 +30,10 @@ select
.opblock-body select
{
min-width: 230px;
@media (max-width: 768px)
{
min-width: 180px;
}
}
label
@@ -53,9 +57,13 @@ input[type=file]
margin: 5px 0;
padding: 8px 10px;
border: 1px solid #d9d9d9;
border: 1px solid $form-input-border-color;
border-radius: 4px;
background: #fff;
background: $form-input-background-color;
@media (max-width: 768px) {
max-width: 175px;
}
&.invalid
{
@@ -102,13 +110,13 @@ textarea
border: none;
border-radius: 4px;
outline: none;
background: rgba(#fff,.8);
background: rgba($form-textarea-background-color,.8);
@include text_code();
&:focus
{
border: 2px solid $_color-get;
border: 2px solid $form-textarea-focus-border-color;
}
&.curl
@@ -122,9 +130,9 @@ textarea
resize: none;
border-radius: 4px;
background: #41444e;
background: $form-textarea-curl-background-color;
@include text_code(#fff);
@include text_code($form-textarea-curl-font-color);
}
}
@@ -135,7 +143,7 @@ textarea
transition: opacity .5s;
color: #333;
color: $form-checkbox-label-font-color;
label
{
@@ -171,8 +179,8 @@ textarea
cursor: pointer;
border-radius: 1px;
background: #e8e8e8;
box-shadow: 0 0 0 2px #e8e8e8;
background: $form-checkbox-background-color;
box-shadow: 0 0 0 2px $form-checkbox-box-shadow-color;
flex: none;
@@ -184,7 +192,7 @@ textarea
&:checked + label > .item
{
background: #e8e8e8 url(data:image/svg+xml,%0A%3Csvg%20width%3D%2210px%22%20height%3D%228px%22%20viewBox%3D%223%207%2010%208%22%20version%3D%221.1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%3E%0A%20%20%20%20%3C%21--%20Generator%3A%20Sketch%2042%20%2836781%29%20-%20http%3A//www.bohemiancoding.com/sketch%20--%3E%0A%20%20%20%20%3Cdesc%3ECreated%20with%20Sketch.%3C/desc%3E%0A%20%20%20%20%3Cdefs%3E%3C/defs%3E%0A%20%20%20%20%3Cpolygon%20id%3D%22Rectangle-34%22%20stroke%3D%22none%22%20fill%3D%22%2341474E%22%20fill-rule%3D%22evenodd%22%20points%3D%226.33333333%2015%203%2011.6666667%204.33333333%2010.3333333%206.33333333%2012.3333333%2011.6666667%207%2013%208.33333333%22%3E%3C/polygon%3E%0A%3C/svg%3E) center center no-repeat;
background: $form-checkbox-background-color url(data:image/svg+xml,%0A%3Csvg%20width%3D%2210px%22%20height%3D%228px%22%20viewBox%3D%223%207%2010%208%22%20version%3D%221.1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%3E%0A%20%20%20%20%3C%21--%20Generator%3A%20Sketch%2042%20%2836781%29%20-%20http%3A//www.bohemiancoding.com/sketch%20--%3E%0A%20%20%20%20%3Cdesc%3ECreated%20with%20Sketch.%3C/desc%3E%0A%20%20%20%20%3Cdefs%3E%3C/defs%3E%0A%20%20%20%20%3Cpolygon%20id%3D%22Rectangle-34%22%20stroke%3D%22none%22%20fill%3D%22%2341474E%22%20fill-rule%3D%22evenodd%22%20points%3D%226.33333333%2015%203%2011.6666667%204.33333333%2010.3333333%206.33333333%2012.3333333%2011.6666667%207%2013%208.33333333%22%3E%3C/polygon%3E%0A%3C/svg%3E) center center no-repeat;
}
}
}
+6 -6
View File
@@ -30,9 +30,9 @@
padding: 3px 5px;
border-radius: 4px;
background: rgba(#000,.05);
background: rgba($info-code-background-color,.05);
@include text_code(#9012fe);
@include text_code($info-code-font-color);
}
a
@@ -41,11 +41,11 @@
transition: all .4s;
@include text_body(#4990e2);
@include text_body($info-link-font-color);
&:hover
{
color: darken(#4990e2, 15%);
color: darken($info-link-font-color-hover, 15%);
}
}
> div
@@ -86,13 +86,13 @@
vertical-align: super;
border-radius: 57px;
background: #7d8492;
background: $info-title-small-background-color;
pre
{
margin: 0;
@include text_headline(#fff);
@include text_headline($info-title-small-pre-font-color);
}
}
}
+35 -39
View File
@@ -34,11 +34,11 @@
cursor: pointer;
transition: all .2s;
border-bottom: 1px solid rgba(#3b4151, .3);
border-bottom: 1px solid rgba($opblock-tag-border-bottom-color, .3);
&:hover
{
background: rgba(#000,.02);
background: rgba($opblock-tag-background-color-hover,.02);
}
}
@@ -127,9 +127,9 @@
{
margin: 0 0 15px 0;
border: 1px solid #000;
border: 1px solid $opblock-border-color;
border-radius: 4px;
box-shadow: 0 0 3px rgba(#000,.19);
box-shadow: 0 0 3px rgba($opblock-box-shadow-color,.19);
.tab-header
{
@@ -168,7 +168,7 @@
content: '';
transform: translateX(-50%);
background: #888;
background: $opblock-tab-header-tab-item-active-h4-span-after-background-color;
}
}
}
@@ -181,7 +181,7 @@
{
.opblock-summary
{
border-bottom: 1px solid #000;
border-bottom: 1px solid $opblock-isopen-summary-border-bottom-color;
}
}
@@ -194,8 +194,8 @@
min-height: 50px;
background: rgba(#fff,.8);
box-shadow: 0 1px 2px rgba(#000,.1);
background: rgba($opblock-isopen-section-header-background-color,.8);
box-shadow: 0 1px 2px rgba($opblock-isopen-section-header-box-shadow-color,.1);
label
{
@@ -239,10 +239,10 @@
text-align: center;
border-radius: 3px;
background: #000;
text-shadow: 0 1px 0 rgba(#000,.1);
background: $opblock-summary-method-background-color;
text-shadow: 0 1px 0 rgba($opblock-summary-method-text-shadow-color,.1);
@include text_headline(#fff);
@include text_headline($opblock-summary-method-font-color);
}
.opblock-summary-path,
@@ -250,6 +250,10 @@
.opblock-summary-path__deprecated
{
font-size: 16px;
@media (max-width: 768px) {
font-size: 12px;
}
display: flex;
flex: 0 3 auto;
@@ -373,7 +377,7 @@
margin: 20px 0;
padding: 10px 10px;
border: 2px solid #d8dde7;
border: 2px solid $operational-filter-input-border-color;
}
}
@@ -416,7 +420,7 @@
content: '';
background: rgba(#000,.2);
background: rgba($tab-list-item-first-background-color,.2);
}
}
@@ -521,7 +525,7 @@
{
font-size: 11px;
@include text_code(#999);
@include text_code($response-col-status-undocumented-font-color);
}
}
@@ -537,7 +541,7 @@
{
font-size: 11px;
@include text_code(#999);
@include text_code($response-col-links-font-color);
}
}
@@ -554,9 +558,9 @@
padding: 10px;
border-radius: 4px;
background: #41444e;
background: $response-col-description-inner-markdown-background-color;
@include text_code(#fff);
@include text_code($response-col-description-inner-markdown-font-color);
p
{
@@ -565,10 +569,10 @@
a
{
@include text_code(#89bf04);
@include text_code($response-col-description-inner-markdown-link-font-color);
text-decoration: underline;
&:hover {
color: #81b10c;
color: $response-col-description-inner-markdown-link-font-color-hover;
}
}
}
@@ -589,13 +593,13 @@
hyphens: auto;
border-radius: 4px;
background: #41444e;
background: $opblock-body-background-color;
overflow-wrap: break-word;
@include text_code(#fff);
@include text_code($opblock-body-font-color);
span
{
color: #fff !important;
color: $opblock-body-font-color !important;
}
.headerline
@@ -609,8 +613,8 @@
margin: 0 0 20px 0;
padding: 30px 0;
background: #fff;
box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);
background: $scheme-container-background-color;
box-shadow: 0 1px 2px 0 rgba($scheme-container-box-shadow-color,.15);
.schemes
{
@@ -644,14 +648,14 @@
margin: 0 0 20px 0;
padding: 30px 0;
background: #fff;
box-shadow: 0 1px 2px 0 rgba(0,0,0,.15);
background: $server-container-background-color;
box-shadow: 0 1px 2px 0 rgba($server-container-box-shadow-color,.15);
.computed-url {
margin: 2em 0;
code {
color: grey;
color: $server-container-computed-url-code-font-color;
display: inline-block;
padding: 4px;
font-size: 16px;
@@ -751,8 +755,8 @@
animation: rotation 1s infinite linear, opacity .5s;
opacity: 1;
border: 2px solid rgba(#555, .1);
border-top-color: rgba(#000, .6);
border: 2px solid rgba($loading-container-before-border-color, .1);
border-top-color: rgba($loading-container-before-border-top-color, .6);
border-radius: 100%;
backface-visibility: hidden;
@@ -768,24 +772,16 @@
}
}
.renderedMarkdown {
p {
@include text_body();
margin-top: 0px;
margin-bottom: 0px;
}
}
.response-content-type {
padding-top: 1em;
&.controls-accept-header {
select {
border-color: green;
border-color: $response-content-type-controls-accept-header-select-border-color;
}
small {
color: green;
color: $response-content-type-controls-accept-header-small-font-color;
font-size: .7em;
}
}
+6 -6
View File
@@ -15,7 +15,7 @@
bottom: 0;
left: 0;
background: rgba(#000,.8);
background: rgba($dialog-ux-backdrop-background-color,.8);
}
.modal-ux
@@ -31,10 +31,10 @@
transform: translate(-50%,-50%);
border: 1px solid #ebebeb;
border: 1px solid $dialog-ux-modal-border-color;
border-radius: 4px;
background: #fff;
box-shadow: 0 10px 30px 0 rgba(0,0,0,.20);
background: $dialog-ux-modal-background-color;
box-shadow: 0 10px 30px 0 rgba($dialog-ux-modal-box-shadow-color,.20);
}
.modal-ux-content
@@ -50,7 +50,7 @@
margin: 0 0 5px 0;
color: #41444e;
color: $dialog-ux-modal-content-font-color;
@include text_body();
}
@@ -72,7 +72,7 @@
padding: 12px 0;
border-bottom: 1px solid #ebebeb;
border-bottom: 1px solid $dialog-ux-modal-header-border-bottom-color;
align-items: center;
+14 -14
View File
@@ -6,7 +6,7 @@
.deprecated
{
span, td {
color: #aaa !important;
color: $model-deprecated-font-color !important;
}
}
@@ -82,9 +82,9 @@
white-space: nowrap;
color: #ebebeb;
color: $model-hint-font-color;
border-radius: 4px;
background: rgba(#000,.7);
background: rgba($model-hint-background-color,.7);
}
p {
@@ -97,7 +97,7 @@ section.models
{
margin: 30px 0;
border: 1px solid rgba(#3b4151, .3);
border: 1px solid rgba($section-models-border-color, .3);
border-radius: 4px;
&.is-open
@@ -106,7 +106,7 @@ section.models
h4
{
margin: 0 0 5px 0;
border-bottom: 1px solid rgba(#3b4151, .3);
border-bottom: 1px solid rgba($section-models-isopen-h4-border-bottom-color, .3);
}
}
h4
@@ -121,7 +121,7 @@ section.models
cursor: pointer;
transition: all .2s;
@include text_headline(#777);
@include text_headline($section-models-h4-font-color);
align-items: center;
svg
@@ -136,7 +136,7 @@ section.models
&:hover
{
background: rgba(#000,.02);
background: rgba($section-models-h4-background-color-hover,.02);
}
}
@@ -146,7 +146,7 @@ section.models
margin: 0 0 10px 0;
@include text_headline(#777);
@include text_headline($section-models-h5-font-color);
}
.model-jump-to-path
@@ -162,11 +162,11 @@ section.models
transition: all .5s;
border-radius: 4px;
background: rgba(#000,.05);
background: rgba($section-models-model-container-background-color,.05);
&:hover
{
background: rgba(#000,.07);
background: rgba($section-models-model-container-background-color,.07);
}
&:first-of-type
@@ -192,7 +192,7 @@ section.models
padding: 10px;
border-radius: 4px;
background: rgba(#000,.1);
background: rgba($section-models-model-box-background-color,.1);
.model-jump-to-path
{
@@ -211,7 +211,7 @@ section.models
{
font-size: 16px;
@include text_headline(#555);
@include text_headline($section-models-model-title-font-color);
}
.model-deprecated-warning
@@ -243,7 +243,7 @@ span
.prop-type
{
color: #55a;
color: $prop-type-font-color;
}
.prop-enum
@@ -252,5 +252,5 @@ span
}
.prop-format
{
color: #999;
color: $prop-format-font-color;
}
+4 -4
View File
@@ -74,7 +74,7 @@ table
text-align: left;
border-bottom: 1px solid rgba(#3b4151, .2);
border-bottom: 1px solid rgba($table-thead-td-border-bottom-color, .2);
@include text_body();
}
@@ -126,7 +126,7 @@ table
content: 'required';
color: rgba(#f00, .6);
color: rgba($table-parameter-name-required-font-color, .6);
}
}
}
@@ -136,7 +136,7 @@ table
font-size: 12px;
font-style: italic;
@include text_code(#888);
@include text_code($table-parameter-in-font-color);
}
.parameter__deprecated
@@ -144,7 +144,7 @@ table
font-size: 12px;
font-style: italic;
@include text_code(#f00);
@include text_code($table-parameter-deprecated-font-color);
}
+8 -9
View File
@@ -1,8 +1,8 @@
.topbar
{
padding: 8px 30px;
padding: 8px 0;
background-color: #89bf04;
background-color: $topbar-background-color;
.topbar-wrapper
{
display: flex;
@@ -21,7 +21,7 @@
text-decoration: none;
@include text_headline(#fff);
@include text_headline($topbar-link-font-color);
span
{
@@ -39,10 +39,9 @@
input[type=text]
{
width: 100%;
min-width: 350px;
margin: 0;
border: 2px solid #547f00;
border: 2px solid $topbar-download-url-wrapper-element-border-color;
border-radius: 4px 0 0 4px;
outline: none;
}
@@ -72,7 +71,7 @@
width: 100%;
border: 2px solid #547f00;
border: 2px solid $topbar-download-url-wrapper-element-border-color;
outline: none;
box-shadow: none;
}
@@ -84,13 +83,13 @@
font-size: 16px;
font-weight: bold;
padding: 4px 40px;
padding: 4px 30px;
border: none;
border-radius: 0 4px 4px 0;
background: #547f00;
background: $topbar-download-url-button-background-color;
@include text_headline(#fff);
@include text_headline($topbar-download-url-button-font-color);
}
}
}
+3 -3
View File
@@ -1,11 +1,11 @@
@mixin text_body($color: #3b4151)
@mixin text_body($color: $text-body-default-font-color)
{
font-family: 'Open Sans', sans-serif;
color: $color;
}
@mixin text_code($color: #3b4151)
@mixin text_code($color: $text-code-default-font-color)
{
font-family: 'Source Code Pro', monospace;
font-weight: 600;
@@ -13,7 +13,7 @@
color: $color;
}
@mixin text_headline($color: #3b4151)
@mixin text_headline($color: $text-headline-default-font-color)
{
font-family: 'Titillium Web', sans-serif;
+218
View File
@@ -0,0 +1,218 @@
$gray-base: #000 !default;
$white: #fff !default;
$gray-50: #ebebeb !default;
$gray-100: #d8dde7 !default;
$gray-200: lighten($gray-base, 62.75%) !default; // #aaa
$gray-300: lighten($gray-base, 56.5%) !default; // #999
$gray-400: lighten($gray-base, 50%) !default; // #888
$gray-500: lighten($gray-base, 43.75%) !default; // #777
$gray-600: lighten($gray-base, 37.5%) !default; // #666
$gray-650: lighten($gray-base, 33.3%) !default; // ##555555
$gray-700: lighten($gray-base, 31.25%) !default; // #555
$gray-800: lighten($gray-base, 25%) !default; // #444
$gray-900: lighten($gray-base, 18.75%) !default; // #333
$gray-custom-1: #41444e !default;
$gray-custom-2: #3b4151 !default;
$color-primary: #89bf04 !default;
$color-secondary: #9012fe !default;
$color-info: #4990e2 !default;
$color-warning: #ff6060 !default;
$color-danger: #f00 !default;
$_color-post: #49cc90 !default;
$_color-get: #61affe !default;
$_color-put: #fca130 !default;
$_color-delete: #f93e3e !default;
$_color-head: #9012fe !default;
$_color-patch: #50e3c2 !default;
$_color-disabled: #ebebeb !default;
$_color-options: #0d5aa7 !default;
$color-green: #008000 !default;
$color-primary-hover: #81b10c !default;
// Authorize
$auth-container-border-color: $gray-50 !default;
// Buttons
$btn-background-color: transparent !default;
$btn-border-color: $gray-400 !default;
$btn-font-color: inherit !default;
$btn-box-shadow-color: $gray-base !default;
$btn-authorize-background-color: transparent !default;
$btn-authorize-border-color: $_color-post !default;
$btn-authorize-font-color: $_color-post !default;
$btn-authorize-svg-fill-color: $_color-post !default;
$btn-cancel-background-color: transparent !default;
$btn-cancel-border-color: $color-warning !default;
$btn-cancel-font-color: $color-warning !default;
$btn-execute-background-color: transparent !default;
$btn-execute-border-color: $color-info !default;
$btn-execute-font-color: $white !default;
$btn-execute-background-color-alt: $color-info !default;
$expand-methods-svg-fill-color: $gray-500 !default;
$expand-methods-svg-fill-color-hover: $gray-800 !default;
// Errors
$errors-wrapper-background-color: $_color-delete !default;
$errors-wrapper-border-color: $_color-delete !default;
$errors-wrapper-errors-small-font-color: $gray-600 !default;
// Form
$form-select-background-color: #f7f7f7 !default;
$form-select-border-color: $gray-custom-1 !default;
$form-select-box-shadow-color: $gray-base !default;
$form-input-border-color: #d9d9d9 !default;
$form-input-background-color: $white !default;
$form-textarea-background-color: $white !default;
$form-textarea-focus-border-color: $_color-get !default;
$form-textarea-curl-background-color: $gray-custom-1 !default;
$form-textarea-curl-font-color: $white !default;
$form-checkbox-label-font-color: $gray-900 !default;
$form-checkbox-background-color: #e8e8e8 !default;
$form-checkbox-box-shadow-color: #e8e8e8 !default;
// Information
$info-code-background-color: $gray-base !default;
$info-code-font-color: $_color-head !default;
$info-link-font-color: $color-info !default;
$info-link-font-color-hover: $info-link-font-color !default;
$info-title-small-background-color: #7d8492 !default;
$info-title-small-pre-font-color: $white !default;
// Layout
$opblock-border-color: $gray-base !default;
$opblock-box-shadow-color: $gray-base !default;
$opblock-tag-border-bottom-color: $gray-custom-2 !default;
$opblock-tag-background-color-hover: $gray-base !default;
$opblock-tab-header-tab-item-active-h4-span-after-background-color: $gray-400 !default;
$opblock-isopen-summary-border-bottom-color: $gray-base !default;
$opblock-isopen-section-header-background-color: $white !default;
$opblock-isopen-section-header-box-shadow-color: $gray-base !default;
$opblock-summary-method-background-color: $gray-base !default;
$opblock-summary-method-font-color: $white !default;
$opblock-summary-method-text-shadow-color: $gray-base !default;
$operational-filter-input-border-color: #d8dde7 !default;
$tab-list-item-first-background-color: $gray-base !default;
$response-col-status-undocumented-font-color: $gray-300 !default;
$response-col-links-font-color: $gray-300 !default;
$response-col-description-inner-markdown-font-color: $white !default;
$response-col-description-inner-markdown-background-color: $gray-custom-1 !default;
$response-col-description-inner-markdown-link-font-color: $color-primary !default;
$response-col-description-inner-markdown-link-font-color-hover: $color-primary-hover !default;
$opblock-body-background-color: $gray-custom-1 !default;
$opblock-body-font-color: $white !default;
$scheme-container-background-color: $white !default;
$scheme-container-box-shadow-color: $gray-base !default;
$server-container-background-color: $white !default;
$server-container-box-shadow-color: $gray-base !default;
$server-container-computed-url-code-font-color: $gray-400 !default;
$loading-container-before-border-color: $gray-650 !default;
$loading-container-before-border-top-color: $gray-base !default;
$response-content-type-controls-accept-header-select-border-color: $color-green !default;
$response-content-type-controls-accept-header-small-font-color: $color-green !default;
// Modal
$dialog-ux-backdrop-background-color: $gray-base !default;
$dialog-ux-modal-background-color: $white !default;
$dialog-ux-modal-border-color: $gray-50 !default;
$dialog-ux-modal-box-shadow-color: $gray-base !default;
$dialog-ux-modal-content-font-color: $gray-custom-1 !default;
$dialog-ux-modal-header-border-bottom-color: $gray-50 !default;
// Models
$model-deprecated-font-color: $gray-200 !default;
$model-hint-font-color: $gray-50 !default;
$model-hint-background-color: $gray-base !default;
$section-models-border-color: $gray-custom-2 !default;
$section-models-isopen-h4-border-bottom-color: $section-models-border-color !default;
$section-models-h4-font-color: $gray-500 !default;
$section-models-h4-background-color-hover: $gray-base !default;
$section-models-h5-font-color: $gray-500 !default;
$section-models-model-container-background-color: $gray-base !default;
$section-models-model-box-background-color: $gray-base !default;
$section-models-model-title-font-color: $gray-700 !default;
$prop-type-font-color: #55a !default;
$prop-format-font-color: $gray-300 !default;
// Tables
$table-thead-td-border-bottom-color: $gray-custom-2 !default;
$table-parameter-name-required-font-color: $color-danger !default;
$table-parameter-in-font-color: $gray-400 !default;
$table-parameter-deprecated-font-color: $color-danger !default;
// Topbar
$topbar-background-color: $color-primary !default;
$topbar-link-font-color: $white !default;
$topbar-download-url-wrapper-element-border-color: #547f00 !default;
$topbar-download-url-button-background-color: #547f00 !default;
$topbar-download-url-button-font-color: $white !default;
// Type
$text-body-default-font-color: $gray-custom-2 !default;
$text-code-default-font-color: $gray-custom-2 !default;
$text-headline-default-font-color: $gray-custom-2 !default;
+6
View File
@@ -24,6 +24,12 @@ describe("Markdown component", function() {
const el = render(<Markdown source={str} />)
expect(el.html()).toEqual(`<div class="markdown"><h1>h1</h1>\n<h2>h2</h2>\n<h3>h3</h3>\n<h4>h4</h4>\n<h5>h5</h5>\n<h6>h6</h6>\n</div>`)
})
it("allows links", function() {
const str = `[Link](https://example.com/)`
const el = render(<Markdown source={str} />)
expect(el.html()).toEqual(`<div class="markdown"><p><a href="https://example.com/" target="_blank">Link</a></p>\n</div>`)
})
})
describe("OAS 3", function() {
@@ -0,0 +1,116 @@
/* eslint-env mocha */
import expect, { createSpy } from "expect"
import { Map, fromJS } from "immutable"
import {
definitionsToAuthorize
} from "corePlugins/oas3/auth-extensions/wrap-selectors"
describe("oas3 plugin - auth extensions - wrapSelectors", function(){
describe("execute", function(){
it("should add `securities` to the oriAction call", function(){
// Given
const system = {
getSystem: () => system,
specSelectors: {
specJson: () => fromJS({
openapi: "3.0.0"
}),
securityDefinitions: () => {
return fromJS({
"oauth2AuthorizationCode": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl": "http://google.com/",
"tokenUrl": "http://google.com/",
"scopes": {
"myScope": "our only scope"
}
}
}
},
"oauth2Multiflow": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "http://google.com/",
"scopes": {
"myScope": "our only scope"
}
},
"password": {
"tokenUrl": "http://google.com/",
"scopes": {
"myScope": "our only scope"
}
},
"authorizationCode": {
"authorizationUrl": "http://google.com/",
"tokenUrl": "http://google.com/",
"scopes": {
"myScope": "our only scope"
}
}
}
}
})
}
}
}
// When
let res = definitionsToAuthorize(() => null, system)()
// Then
expect(res.toJS()).toEqual([
{
oauth2AuthorizationCode: {
flow: "authorizationCode",
authorizationUrl: "http://google.com/",
tokenUrl: "http://google.com/",
scopes: {
"myScope": "our only scope"
},
type: "oauth2"
}
},
{
oauth2Multiflow: {
flow: "clientCredentials",
tokenUrl: "http://google.com/",
scopes: {
"myScope": "our only scope"
},
type: "oauth2"
}
},
{
oauth2Multiflow: {
flow: "password",
tokenUrl: "http://google.com/",
scopes: {
"myScope": "our only scope"
},
type: "oauth2"
}
},
{
oauth2Multiflow: {
flow: "authorizationCode",
authorizationUrl: "http://google.com/",
tokenUrl: "http://google.com/",
scopes: {
"myScope": "our only scope"
},
type: "oauth2"
}
},
])
})
})
})
+76 -12
View File
@@ -3,6 +3,7 @@ import expect from "expect"
import { fromJS, OrderedMap } from "immutable"
import {
mapToList,
validatePattern,
validateMinLength,
validateMaxLength,
validateDateTime,
@@ -16,7 +17,8 @@ import {
fromJSOrdered,
getAcceptControllingResponse,
createDeepLinkPath,
escapeDeepLinkPath
escapeDeepLinkPath,
sanitizeUrl
} from "core/utils"
import win from "core/window"
@@ -215,9 +217,9 @@ describe("utils", function() {
expect(validateFile(1)).toEqual(errorMessage)
expect(validateFile("string")).toEqual(errorMessage)
})
})
})
describe("validateDateTime", function() {
describe("validateDateTime", function() {
let errorMessage = "Value must be a DateTime"
it("doesn't return for valid dates", function() {
@@ -228,7 +230,7 @@ describe("utils", function() {
expect(validateDateTime(null)).toEqual(errorMessage)
expect(validateDateTime("string")).toEqual(errorMessage)
})
})
})
describe("validateGuid", function() {
let errorMessage = "Value must be a Guid"
@@ -242,9 +244,9 @@ describe("utils", function() {
expect(validateGuid(1)).toEqual(errorMessage)
expect(validateGuid("string")).toEqual(errorMessage)
})
})
})
describe("validateMaxLength", function() {
describe("validateMaxLength", function() {
let errorMessage = "Value must be less than MaxLength"
it("doesn't return for valid guid", function() {
@@ -257,9 +259,9 @@ describe("utils", function() {
expect(validateMaxLength("abc", 1)).toEqual(errorMessage)
expect(validateMaxLength("abc", 2)).toEqual(errorMessage)
})
})
})
describe("validateMinLength", function() {
describe("validateMinLength", function() {
let errorMessage = "Value must be greater than MinLength"
it("doesn't return for valid guid", function() {
@@ -271,7 +273,29 @@ describe("utils", function() {
expect(validateMinLength("abc", 5)).toEqual(errorMessage)
expect(validateMinLength("abc", 8)).toEqual(errorMessage)
})
})
})
describe("validatePattern", function() {
let rxPattern = "^(red|blue)"
let errorMessage = "Value must follow pattern " + rxPattern
it("doesn't return for a match", function() {
expect(validatePattern("red", rxPattern)).toBeFalsy()
expect(validatePattern("blue", rxPattern)).toBeFalsy()
})
it("returns a message for invalid pattern", function() {
expect(validatePattern("pink", rxPattern)).toEqual(errorMessage)
expect(validatePattern("123", rxPattern)).toEqual(errorMessage)
})
it("fails gracefully when an invalid regex value is passed", function() {
expect(() => validatePattern("aValue", "---")).toNotThrow()
expect(() => validatePattern("aValue", 1234)).toNotThrow()
expect(() => validatePattern("aValue", null)).toNotThrow()
expect(() => validatePattern("aValue", [])).toNotThrow()
})
})
describe("validateParam", function() {
let param = null
@@ -524,7 +548,7 @@ describe("utils", function() {
type: "boolean",
value: "test string"
}
assertValidateParam(param, ["Required field is not provided"])
assertValidateParam(param, ["Value must be a boolean"])
// valid boolean value
param = {
@@ -584,7 +608,7 @@ describe("utils", function() {
type: "number",
value: "test"
}
assertValidateParam(param, ["Required field is not provided"])
assertValidateParam(param, ["Value must be a number"])
// invalid number, undefined value
param = {
@@ -666,7 +690,7 @@ describe("utils", function() {
type: "integer",
value: "test"
}
assertValidateParam(param, ["Required field is not provided"])
assertValidateParam(param, ["Value must be an integer"])
// invalid integer, undefined value
param = {
@@ -885,4 +909,44 @@ describe("utils", function() {
expect(result).toEqual("hello\\#world")
})
})
describe("sanitizeUrl", function() {
it("should sanitize a `javascript:` url", function() {
const res = sanitizeUrl("javascript:alert('bam!')")
expect(res).toEqual("about:blank")
})
it("should sanitize a `data:` url", function() {
const res = sanitizeUrl(`data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGV
sbG8iKTs8L3NjcmlwdD4=`)
expect(res).toEqual("about:blank")
})
it("should not modify a `http:` url", function() {
const res = sanitizeUrl(`http://swagger.io/`)
expect(res).toEqual("http://swagger.io/")
})
it("should not modify a `https:` url", function() {
const res = sanitizeUrl(`https://swagger.io/`)
expect(res).toEqual("https://swagger.io/")
})
it("should gracefully handle empty strings", function() {
expect(sanitizeUrl("")).toEqual("")
})
it("should gracefully handle non-string values", function() {
expect(sanitizeUrl(123)).toEqual("")
expect(sanitizeUrl(null)).toEqual("")
expect(sanitizeUrl(undefined)).toEqual("")
expect(sanitizeUrl([])).toEqual("")
expect(sanitizeUrl({})).toEqual("")
})
})
})
+1 -1
View File
@@ -11,7 +11,7 @@ let rules = [
name: "[name].js"
}
},
{ loader: "babel-loader" }
{ loader: "babel-loader?retainLines=true" }
]
}
]
+1 -1
View File
@@ -11,7 +11,7 @@ let rules = [
name: "[name].js"
}
},
{ loader: "babel-loader" }
{ loader: "babel-loader?retainLines=true" }
]
}
]
+1 -1
View File
@@ -13,7 +13,7 @@ let rules = [
name: "[name].js"
}
},
{ loader: "babel-loader" }
{ loader: "babel-loader?retainLines=true" }
]
}
]
+2 -8
View File
@@ -9,13 +9,7 @@ const rules = [
inline: true
}
},
{ loader: "babel-loader" }
]
},
{ test: /\.(jsx)(\?.*)?$/,
use: [
{ loader: "react-hot-loader" },
{ loader: "babel-loader" }
{ loader: "babel-loader?retainLines=true" }
]
},
{ test: /\.(css)(\?.*)?$/,
@@ -48,7 +42,7 @@ module.exports = require("./make-webpack-config")(rules, {
_special: {
separateStylesheets: false,
},
devtool: "eval",
devtool: "eval-source-map",
entry: {
"swagger-ui-bundle": [
"./src/polyfills",