Merge branch 'master' into lock-client-version

This commit is contained in:
shockey
2017-06-22 20:45:57 -07:00
committed by GitHub
53 changed files with 366 additions and 7086 deletions

View File

@@ -5,6 +5,7 @@
"stage-0" "stage-0"
], ],
"plugins": [ "plugins": [
"transform-runtime",
[ [
"module-alias", "module-alias",
[ [

View File

@@ -22,7 +22,7 @@
"rules": { "rules": {
"semi": [2, "never"], "semi": [2, "never"],
"strict": 0, "strict": 0,
"quotes": 2, "quotes": [2, "double", { "allowTemplateLiterals": true }],
"no-unused-vars": 2, "no-unused-vars": 2,
"no-multi-spaces": 1, "no-multi-spaces": 1,
"camelcase": 1, "camelcase": 1,

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
docker-run.sh text eol=lf

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ node_modules
.DS_Store .DS_Store
npm-debug.log* npm-debug.log*
.eslintcache .eslintcache
package-lock.json

View File

@@ -1,4 +1,4 @@
FROM alpine:3.4 FROM alpine:3.5
MAINTAINER fehguy MAINTAINER fehguy

View File

@@ -6,8 +6,15 @@
**This is the new version of swagger-ui, 3.x. Want to learn more? Check out our [FAQ](http://swagger.io/new-ui-faq/).** **This is the new version of swagger-ui, 3.x. Want to learn more? Check out our [FAQ](http://swagger.io/new-ui-faq/).**
**👉🏼 Want to score an easy open-source contribution?** Check out our [Good first contribution](https://github.com/swagger-api/swagger-ui/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+contribution%22) label.
As a brand new version, written from the ground up, there are some known issues and unimplemented features. Check out the [Known Issues](#known-issues) section for more details. As a brand new version, written from the ground up, there are some known issues and unimplemented features. Check out the [Known Issues](#known-issues) section for more details.
This repo publishes to two different NPM packages:
* [swagger-ui](https://www.npmjs.com/package/swagger-ui) is intended for use as a node module.
* [swagger-ui-dist](https://www.npmjs.com/package/swagger-ui-dist) comes pre-bundled with all dependencies and can be incorporated directly in a webapp.
For the older version of swagger-ui, refer to the [*2.x branch*](https://github.com/swagger-api/swagger-ui/tree/2.x). For the older version of swagger-ui, refer to the [*2.x branch*](https://github.com/swagger-api/swagger-ui/tree/2.x).
## Compatibility ## Compatibility
@@ -15,7 +22,7 @@ The OpenAPI Specification has undergone 4 revisions since initial creation in 20
Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | Status Swagger UI Version | Release Date | OpenAPI Spec compatibility | Notes | Status
------------------ | ------------ | -------------------------- | ----- | ------ ------------------ | ------------ | -------------------------- | ----- | ------
3.0.12 | 2017-03-19 | 2.0 | [tag v3.0.12](https://github.com/swagger-api/swagger-ui/tree/v3.0.12) | 3.0.16 | 2017-06-17 | 2.0 | [tag v3.0.16](https://github.com/swagger-api/swagger-ui/tree/v3.0.16) |
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.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.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) | 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) |
@@ -35,6 +42,12 @@ docker run -p 80:8080 swaggerapi/swagger-ui
Will start nginx with swagger-ui on port 80. Will start nginx with swagger-ui on port 80.
Or you can provide your own swagger.json on your host
```
docker run -p 80:8080 -e "SWAGGER_JSON=/foo/swagger.json" -v /bar:/foo swaggerapi/swagger-ui
```
##### Prerequisites ##### Prerequisites
- Node 6.x - Node 6.x
- NPM 3.x - NPM 3.x
@@ -59,6 +72,11 @@ To help with the migration, here are the currently known issues with 3.X. This l
- l10n (translations) is not implemented. - l10n (translations) is not implemented.
- Relative path support for external files is not implemented. - Relative path support for external files is not implemented.
### Direct use of JS and CSS assets
To include the JS, CSS and image assets directly into a webpage, use the [swagger-ui-dist](https://www.npmjs.com/package/swagger-ui-dist) package.
The root directory of this package contains the contents of the _dist/_ directory of this repo.
As a node module, `swagger-ui-dist` also exports the `swagger-ui-bundle` and `swagger-ui-standalone-preset` objects.
### SwaggerUIBundle ### SwaggerUIBundle
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: 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:
@@ -119,6 +137,8 @@ operationsSorter | Apply a sort to the operation list of each API. It can be 'al
configUrl | Configs URL configUrl | Configs URL
parameterMacro | MUST be a function. Function to set default value to parameters. Accepts two arguments parameterMacro(operation, parameter). Operation and parameter are objects passed for context, both remain immutable parameterMacro | MUST be a function. Function to set default value to parameters. Accepts two arguments parameterMacro(operation, parameter). Operation and parameter are objects passed for context, both remain immutable
modelPropertyMacro | MUST be a function. Function to set default values to each property in model. Accepts one argument modelPropertyMacro(property), property is immutable modelPropertyMacro | MUST be a function. Function to set default values to each property in model. Accepts one argument modelPropertyMacro(property), property is immutable
docExpansion | Controls the default expansion setting for the operations and tags. It can be 'list' (expands only the tags), 'full' (expands the tags and operations) or 'none' (expands nothing). The default is 'list'.
displayOperationId | Controls the display of operationId in operations list. The default is `false`.
### Plugins ### Plugins

View File

@@ -8,6 +8,7 @@
function run () { function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2; var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state; var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr; var isValid, qp, arr;
qp = (window.location.hash || location.search).substring(1); qp = (window.location.hash || location.search).substring(1);
@@ -35,7 +36,7 @@
if (qp.code) { if (qp.code) {
delete oauth2.state; delete oauth2.state;
oauth2.auth.code = qp.code; oauth2.auth.code = qp.code;
oauth2.callback(oauth2.auth); oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else { } else {
oauth2.errCb({ oauth2.errCb({
authId: oauth2.auth.name, authId: oauth2.auth.name,
@@ -45,9 +46,8 @@
}); });
} }
} else { } else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid}); oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
} }
window.close(); window.close();
} }
</script> </script>

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;AAu/FA;AA6+FA;;;;;;;;;;;;;;;;;;;;;;;;;;AAseA;AAkoJA;AAwiCA;AAo9GA;AAw5HA;AAkvGA;AAy7EA;AAoqDA;AAm/CA;AA6jDA;AAk/CA;;;;;AAw2CA;AAmwJA;;;;;;;;;;;;;;AA8sEA;AAyoIA;AAiuJA;AA8kHA;AAonGA;AAukEA;AA02DA;AA45EA;AAu/FA;;;;;;AA04FA;AAk7FA;;;;;AAy/CA;AA2qFA;AAw2CA;AA6kCA;AA68CA;AA+wEA;AA47FA;;;;;;;;;AA48BA;AA2zIA;AAk4DA;AA8mDA;;;;;;AA+9BA;AA8iHA;AAipGA","sourceRoot":""} {"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;AAmqDA;AAorJA;AAiiCA;AAm1GA;AAiwHA;AAg9FA;AAm/EA;AAiuDA;AAq/CA;AAwkDA;AAk/CA;;;;;AA60EA;AA8zJA;;;;;;;;;;;;;;AAyoFA;AA+lIA;AA4oJA;AAqvHA;AAknGA;AA4iEA;AA43DA;AAgnDA;AA6eA;;;;;;AAsvGA;AA+1HA;AA0+DA;;;;;AAwiBA;AAgsFA;AA6kDA;AAq3CA;AA4wFA;AAk3CA;AA2iFA;;;;;;;;;AAwqEA;AA2zIA;AAu7FA;AAmrFA;AAi7EA;;;;;;AAiRA;AA+qHA;AAs7GA","sourceRoot":""}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA+PA;AAyiGA;AAwxFA;;;;;;AA0bA;AAkvFA;AAu+CA;AAo+CA;AAgrCA;AAgyEA","sourceRoot":""} {"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;AA+uFA;;;;;AAyOA;AAo7GA;AAw0FA;;;;;;AAmZA;AA+uFA;AAy+CA;AAo+CA;AAirCA;AAuyEA","sourceRoot":""}

2
dist/swagger-ui.css vendored

File diff suppressed because one or more lines are too long

18
dist/swagger-ui.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA0yCA;AAoyHA;AAgyHA;AAykGA;AA48BA;AAokCA;AA8iCA;AAs6BA","sourceRoot":""} {"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;AAylFA;;;;;;AAg5CA;AA2pHA;AA8qIA;AAi+FA;AAyvDA;AAmzCA;AA+xCA","sourceRoot":""}

View File

@@ -2,7 +2,8 @@
set -e set -e
INDEX_FILE=/usr/share/nginx/html/index.html NGINX_ROOT=/usr/share/nginx/html
INDEX_FILE=$NGINX_ROOT/index.html
replace_in_index () { replace_in_index () {
if [ "$1" != "**None**" ]; then if [ "$1" != "**None**" ]; then
@@ -30,8 +31,10 @@ if [ "$OAUTH_ADDITIONAL_PARAMS" != "**None**" ]; then
fi fi
if [[ -f $SWAGGER_JSON ]]; then if [[ -f $SWAGGER_JSON ]]; then
sed -i "s|http://petstore.swagger.io/v2/swagger.json|swagger.json|g" $INDEX_FILE cp $SWAGGER_JSON $NGINX_ROOT
sed -i "s|http://example.com/api|swagger.json|g" $INDEX_FILE 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 else
sed -i "s|http://petstore.swagger.io/v2/swagger.json|$API_URL|g" $INDEX_FILE sed -i "s|http://petstore.swagger.io/v2/swagger.json|$API_URL|g" $INDEX_FILE
sed -i "s|http://example.com/api|$API_URL|g" $INDEX_FILE sed -i "s|http://example.com/api|$API_URL|g" $INDEX_FILE

View File

@@ -147,7 +147,7 @@ module.exports = function(options) {
extensions: ["", ".web.js", ".js", ".jsx", ".json", ".less"], extensions: ["", ".web.js", ".js", ".jsx", ".json", ".less"],
packageAlias: 'browser', packageAlias: 'browser',
alias: { alias: {
base: "getbase/src/less/base" base: "getbase/src/less/base",
} }
}, },

6912
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "swagger-ui", "name": "swagger-ui",
"version": "3.0.12", "version": "3.0.16",
"main": "dist/swagger-ui.js", "main": "dist/swagger-ui.js",
"repository": "git@github.com:swagger-api/swagger-ui.git", "repository": "git@github.com:swagger-api/swagger-ui.git",
"contributors": [ "contributors": [
@@ -32,10 +32,9 @@
"test": "npm run lint-errors && npm run just-test-in-node", "test": "npm run lint-errors && npm run just-test-in-node",
"test-in-node": "npm run lint-errors && npm run just-test-in-node", "test-in-node": "npm run lint-errors && npm run just-test-in-node",
"just-test": "karma start --config karma.conf.js", "just-test": "karma start --config karma.conf.js",
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components" "just-test-in-node": "mocha --recursive --compilers js:babel-core/register test/core test/components test/bugs test/swagger-ui-dist-package"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "^6.23.0",
"base64-js": "^1.2.0", "base64-js": "^1.2.0",
"brace": "0.7.0", "brace": "0.7.0",
"deep-extend": "0.4.1", "deep-extend": "0.4.1",
@@ -67,14 +66,15 @@
"redux-immutable": "3.0.8", "redux-immutable": "3.0.8",
"redux-logger": "*", "redux-logger": "*",
"reselect": "2.5.3", "reselect": "2.5.3",
"sanitize-html": "^1.14.1",
"serialize-error": "2.0.0", "serialize-error": "2.0.0",
"shallowequal": "0.2.2", "shallowequal": "0.2.2",
"swagger-client": "3.0.12", "swagger-client": "3.0.15",
"url-parse": "^1.1.8", "url-parse": "^1.1.8",
"whatwg-fetch": "0.11.1", "whatwg-fetch": "0.11.1",
"worker-loader": "^0.7.1", "worker-loader": "^0.7.1",
"xml": "1.0.1", "xml": "1.0.1",
"yaml-js": "^0.1.3" "yaml-js": "0.2.0"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "6.6.1", "autoprefixer": "6.6.1",
@@ -82,6 +82,7 @@
"babel-eslint": "^7.1.1", "babel-eslint": "^7.1.1",
"babel-loader": "^6.3.2", "babel-loader": "^6.3.2",
"babel-plugin-module-alias": "^1.6.0", "babel-plugin-module-alias": "^1.6.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.22.0", "babel-preset-es2015": "^6.22.0",
"babel-preset-es2015-ie": "^6.6.2", "babel-preset-es2015-ie": "^6.6.2",
"babel-preset-react": "^6.23.0", "babel-preset-react": "^6.23.0",
@@ -131,7 +132,7 @@
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"last 2 versions", "last 2 versions",
"IE 10" "IE 11"
], ],
"optionalDependencies": { "optionalDependencies": {
"webpack-dev-server": "1.14.0" "webpack-dev-server": "1.14.0"

View File

@@ -53,8 +53,7 @@ export default class ApiKeyAuth extends React.Component {
<h4>Api key authorization<JumpToPath path={[ "securityDefinitions", name ]} /></h4> <h4>Api key authorization<JumpToPath path={[ "securityDefinitions", name ]} /></h4>
{ value && <h6>Authorized</h6>} { value && <h6>Authorized</h6>}
<Row> <Row>
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} <Markdown source={ schema.get("description") } />
source={ schema.get("description") } />
</Row> </Row>
<Row> <Row>
<p>Name: <code>{ schema.get("name") }</code></p> <p>Name: <code>{ schema.get("name") }</code></p>

View File

@@ -59,8 +59,7 @@ export default class BasicAuth extends React.Component {
<h4>Basic authorization<JumpToPath path={[ "securityDefinitions", name ]} /></h4> <h4>Basic authorization<JumpToPath path={[ "securityDefinitions", name ]} /></h4>
{ username && <h6>Authorized</h6> } { username && <h6>Authorized</h6> }
<Row> <Row>
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} <Markdown source={ schema.get("description") } />
source={ schema.get("description") } />
</Row> </Row>
<Row> <Row>
<label>Username:</label> <label>Username:</label>

View File

@@ -27,7 +27,7 @@ export default class Oauth2 extends React.Component {
let username = auth && auth.get("username") || "" let username = auth && auth.get("username") || ""
let clientId = auth && auth.get("clientId") || authConfigs.clientId || "" let clientId = auth && auth.get("clientId") || authConfigs.clientId || ""
let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || "" let clientSecret = auth && auth.get("clientSecret") || authConfigs.clientSecret || ""
let passwordType = auth && auth.get("passwordType") || "basic" let passwordType = auth && auth.get("passwordType") || "request-body"
this.state = { this.state = {
appName: authConfigs.appName, appName: authConfigs.appName,
@@ -97,13 +97,13 @@ export default class Oauth2 extends React.Component {
let isAuthorized = !!authorizedAuth let isAuthorized = !!authorizedAuth
let errors = errSelectors.allErrors().filter( err => err.get("authId") === name) let errors = errSelectors.allErrors().filter( err => err.get("authId") === name)
let isValid = !errors.filter( err => err.get("source") === "validation").size let isValid = !errors.filter( err => err.get("source") === "validation").size
let description = schema.get("description")
return ( return (
<div> <div>
<h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4> <h4>OAuth2.0 <JumpToPath path={[ "securityDefinitions", name ]} /></h4>
{ !this.state.appName ? null : <h5>Application: { this.state.appName } </h5> } { !this.state.appName ? null : <h5>Application: { this.state.appName } </h5> }
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} { description && <Markdown source={ schema.get("description") } /> }
source={ schema.get("description") } />
{ isAuthorized && <h6>Authorized</h6> } { isAuthorized && <h6>Authorized</h6> }

View File

@@ -19,7 +19,7 @@ export default class Curl extends React.Component {
<div> <div>
<h4>Curl</h4> <h4>Curl</h4>
<div className="copy-paste"> <div className="copy-paste">
<textarea onFocus={this.handleFocus} className="curl" style={{ whiteSpace: "normal" }} value={curl}></textarea> <textarea onFocus={this.handleFocus} readOnly="true" className="curl" style={{ whiteSpace: "normal" }} value={curl}></textarea>
</div> </div>
</div> </div>
) )

View File

@@ -99,7 +99,7 @@ export default class Info extends React.Component {
</hgroup> </hgroup>
<div className="description"> <div className="description">
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} source={ description } /> <Markdown source={ description } />
</div> </div>
{ {

View File

@@ -1,13 +1,10 @@
import React, { PropTypes } from "react" import React, { PropTypes } from "react"
import OriCollapse from "react-collapse" import OriCollapse from "react-collapse"
import _Markdown from "react-remarkable"
function xclass(...args) { function xclass(...args) {
return args.filter(a => !!a).join(" ").trim() return args.filter(a => !!a).join(" ").trim()
} }
export const Markdown = _Markdown
export class Container extends React.Component { export class Container extends React.Component {
render() { render() {
let { fullscreen, full, ...rest } = this.props let { fullscreen, full, ...rest } = this.props
@@ -73,7 +70,7 @@ export class Col extends React.Component {
} }
} }
let classes = xclass(rest.className, "clear", ...classesAr) let classes = xclass(rest.className, ...classesAr)
return ( return (
<section {...rest} style={{display: hide ? "none": null}} className={classes}/> <section {...rest} style={{display: hide ? "none": null}} className={classes}/>

View File

@@ -22,13 +22,14 @@ export default class LiveResponse extends React.Component {
render() { render() {
const { request, response, getComponent } = this.props const { request, response, getComponent } = this.props
const body = response.get("text")
const status = response.get("status") const status = response.get("status")
const url = response.get("url") const url = response.get("url")
const headers = response.get("headers").toJS() const headers = response.get("headers").toJS()
const notDocumented = response.get("notDocumented") const notDocumented = response.get("notDocumented")
const isError = response.get("error") const isError = response.get("error")
const body = isError ? response.get("response").get("text") : response.get("text")
const headersKeys = Object.keys(headers) const headersKeys = Object.keys(headers)
const contentType = headers["content-type"] const contentType = headers["content-type"]
@@ -37,6 +38,7 @@ export default class LiveResponse extends React.Component {
const returnObject = headersKeys.map(key => { const returnObject = headersKeys.map(key => {
return <span className="headerline" key={key}> {key}: {headers[key]} </span> return <span className="headerline" key={key}> {key}: {headers[key]} </span>
}) })
const hasHeaders = returnObject.length !== 0
return ( return (
<div> <div>
@@ -54,28 +56,29 @@ export default class LiveResponse extends React.Component {
<td className="col response-col_status"> <td className="col response-col_status">
{ status } { status }
{ {
!notDocumented ? null : notDocumented ? <div className="response-undocumented">
<div className="response-undocumented">
<i> Undocumented </i> <i> Undocumented </i>
</div> </div>
: null
} }
</td> </td>
<td className="col response-col_description"> <td className="col response-col_description">
{ {
!isError ? null : <span> isError ? <span>
{`${response.get("name")}: ${response.get("message")}`} {`${response.get("name")}: ${response.get("message")}`}
</span> </span>
: null
} }
{ {
!body || isError ? null body ? <ResponseBody content={ body }
: <ResponseBody content={ body }
contentType={ contentType } contentType={ contentType }
url={ url } url={ url }
headers={ headers } headers={ headers }
getComponent={ getComponent }/> getComponent={ getComponent }/>
: null
} }
{ {
!headers ? null : <Headers headers={ returnObject }/> hasHeaders ? <Headers headers={ returnObject }/> : null
} }
</td> </td>
</tr> </tr>

View File

@@ -40,6 +40,7 @@ class ObjectModel extends Component {
let additionalProperties = schema.get("additionalProperties") let additionalProperties = schema.get("additionalProperties")
let title = schema.get("title") || name let title = schema.get("title") || name
let required = schema.get("required") let required = schema.get("required")
const Markdown = getComponent("Markdown")
const JumpToPathSection = ({ name }) => <span className="model-jump-to-path"><JumpToPath path={`definitions.${name}`} /></span> const JumpToPathSection = ({ name }) => <span className="model-jump-to-path"><JumpToPath path={`definitions.${name}`} /></span>
let collapsedContent = (<span> let collapsedContent = (<span>
<span>{ braceOpen }</span>...<span>{ braceClose }</span> <span>{ braceOpen }</span>...<span>{ braceClose }</span>
@@ -66,7 +67,9 @@ class ObjectModel extends Component {
{ {
!description ? null : <tr style={{ color: "#999", fontStyle: "italic" }}> !description ? null : <tr style={{ color: "#999", fontStyle: "italic" }}>
<td>description:</td> <td>description:</td>
<td>{ description }</td> <td>
<Markdown source={ description } />
</td>
</tr> </tr>
} }
{ {
@@ -114,11 +117,12 @@ class ObjectModel extends Component {
class Primitive extends Component { class Primitive extends Component {
static propTypes = { static propTypes = {
schema: PropTypes.object.isRequired, schema: PropTypes.object.isRequired,
getComponent: PropTypes.func.isRequired,
required: PropTypes.bool required: PropTypes.bool
} }
render(){ render(){
let { schema, required } = this.props let { schema, getComponent, required } = this.props
if(!schema || !schema.get) { if(!schema || !schema.get) {
// don't render if schema isn't correctly formed // don't render if schema isn't correctly formed
@@ -129,17 +133,23 @@ class Primitive extends Component {
let format = schema.get("format") let format = schema.get("format")
let xml = schema.get("xml") let xml = schema.get("xml")
let enumArray = schema.get("enum") let enumArray = schema.get("enum")
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "$$ref"].indexOf(key) === -1 ) let description = schema.get("description")
let properties = schema.filter( ( v, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1 )
let style = required ? { fontWeight: "bold" } : {} let style = required ? { fontWeight: "bold" } : {}
const Markdown = getComponent("Markdown")
return <span className="prop"> return <span className="prop">
<span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>} <span className="prop-type" style={ style }>{ type }</span> { required && <span style={{ color: "red" }}>*</span>}
{ format && <span className="prop-format">(${format})</span>} { format && <span className="prop-format">(${format})</span>}
{ {
properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }> properties.size ? properties.entrySeq().map( ( [ key, v ] ) => <span key={`${key}-${v}`} style={ propStyle }>
<br />{ key !== "description" && key + ": " }{ String(v) }</span>) <br />{ key }: { String(v) }</span>)
: null : null
} }
{
!description ? null :
<Markdown source={ description } />
}
{ {
xml && xml.size ? (<span><br /><span style={ propStyle }>xml:</span> xml && xml.size ? (<span><br /><span style={ propStyle }>xml:</span>
{ {
@@ -217,7 +227,7 @@ class Model extends Component {
} }
render () { render () {
let { schema, required, name, isRef } = this.props let { schema, getComponent, required, name, isRef } = this.props
let $$ref = schema && schema.get("$$ref") let $$ref = schema && schema.get("$$ref")
let modelName = $$ref && this.getModelName( $$ref ) let modelName = $$ref && this.getModelName( $$ref )
let modelSchema, type let modelSchema, type
@@ -236,7 +246,7 @@ class Model extends Component {
switch(type) { switch(type) {
case "object": case "object":
return <ObjectModel className="object" { ...this.props } schema={ modelSchema } return <ObjectModel className="object" { ...this.props } schema={ modelSchema }
name={ modelName || name } name={ name || modelName }
isRef={ isRef!== undefined ? isRef : !!$$ref }/> isRef={ isRef!== undefined ? isRef : !!$$ref }/>
case "array": case "array":
return <ArrayModel className="array" { ...this.props } schema={ modelSchema } required={ required } /> return <ArrayModel className="array" { ...this.props } schema={ modelSchema } required={ required } />
@@ -245,7 +255,7 @@ class Model extends Component {
case "integer": case "integer":
case "boolean": case "boolean":
default: default:
return <Primitive schema={ modelSchema } required={ required }/> return <Primitive getComponent={ getComponent } schema={ modelSchema } required={ required }/>
} }
} }
} }

View File

@@ -6,13 +6,15 @@ export default class Models extends Component {
getComponent: PropTypes.func, getComponent: PropTypes.func,
specSelectors: PropTypes.object, specSelectors: PropTypes.object,
layoutSelectors: PropTypes.object, layoutSelectors: PropTypes.object,
layoutActions: PropTypes.object layoutActions: PropTypes.object,
getConfigs: PropTypes.func.isRequired
} }
render(){ render(){
let { specSelectors, getComponent, layoutSelectors, layoutActions } = this.props let { specSelectors, getComponent, layoutSelectors, layoutActions, getConfigs } = this.props
let definitions = specSelectors.definitions() let definitions = specSelectors.definitions()
let showModels = layoutSelectors.isShown("models", true) let { docExpansion } = getConfigs()
let showModels = layoutSelectors.isShown("models", docExpansion === "full" || docExpansion === "list" )
const Model = getComponent("model") const Model = getComponent("model")
const Collapse = getComponent("Collapse") const Collapse = getComponent("Collapse")

View File

@@ -17,6 +17,8 @@ export default class Operation extends React.Component {
allowTryItOut: PropTypes.bool, allowTryItOut: PropTypes.bool,
displayOperationId: PropTypes.bool,
response: PropTypes.object, response: PropTypes.object,
request: PropTypes.object, request: PropTypes.object,
@@ -27,13 +29,15 @@ export default class Operation extends React.Component {
specSelectors: PropTypes.object.isRequired, specSelectors: PropTypes.object.isRequired,
layoutActions: PropTypes.object.isRequired, layoutActions: PropTypes.object.isRequired,
layoutSelectors: PropTypes.object.isRequired, layoutSelectors: PropTypes.object.isRequired,
fn: PropTypes.object.isRequired fn: PropTypes.object.isRequired,
getConfigs: PropTypes.func.isRequired
} }
static defaultProps = { static defaultProps = {
showSummary: true, showSummary: true,
response: null, response: null,
allowTryItOut: true, allowTryItOut: true,
displayOperationId: false,
} }
constructor(props, context) { constructor(props, context) {
@@ -76,8 +80,10 @@ export default class Operation extends React.Component {
} }
isShown =() => { isShown =() => {
let { layoutSelectors, isShownKey } = this.props let { layoutSelectors, isShownKey, getConfigs } = this.props
return layoutSelectors.isShown(isShownKey, false ) // Here is where we set the default let { docExpansion } = getConfigs()
return layoutSelectors.isShown(isShownKey, docExpansion === "full" ) // Here is where we set the default
} }
onTryoutClick =() => { onTryoutClick =() => {
@@ -105,6 +111,7 @@ export default class Operation extends React.Component {
response, response,
request, request,
allowTryItOut, allowTryItOut,
displayOperationId,
fn, fn,
getComponent, getComponent,
@@ -123,6 +130,7 @@ export default class Operation extends React.Component {
let produces = operation.get("produces") let produces = operation.get("produces")
let schemes = operation.get("schemes") let schemes = operation.get("schemes")
let parameters = getList(operation, ["parameters"]) let parameters = getList(operation, ["parameters"])
let operationId = operation.get("__originalOperationId")
const Responses = getComponent("responses") const Responses = getComponent("responses")
const Parameters = getComponent( "parameters" ) const Parameters = getComponent( "parameters" )
@@ -159,6 +167,8 @@ export default class Operation extends React.Component {
</div> </div>
} }
{ displayOperationId && operationId ? <span className="opblock-summary-operation-id">{operationId}</span> : null }
{ {
(!security || !security.count()) ? null : (!security || !security.count()) ? null :
<AuthorizeOperationBtn authActions={ authActions } <AuthorizeOperationBtn authActions={ authActions }
@@ -173,7 +183,7 @@ export default class Operation extends React.Component {
{ description && { description &&
<div className="opblock-description-wrapper"> <div className="opblock-description-wrapper">
<div className="opblock-description"> <div className="opblock-description">
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} source={ description } /> <Markdown source={ description } />
</div> </div>
</div> </div>
} }

View File

@@ -10,10 +10,7 @@ export default class Operations extends React.Component {
layoutActions: PropTypes.object.isRequired, layoutActions: PropTypes.object.isRequired,
authActions: PropTypes.object.isRequired, authActions: PropTypes.object.isRequired,
authSelectors: PropTypes.object.isRequired, authSelectors: PropTypes.object.isRequired,
}; getConfigs: PropTypes.func.isRequired
static defaultProps = {
}; };
render() { render() {
@@ -25,6 +22,7 @@ export default class Operations extends React.Component {
layoutActions, layoutActions,
authActions, authActions,
authSelectors, authSelectors,
getConfigs,
fn fn
} = this.props } = this.props
@@ -34,6 +32,7 @@ export default class Operations extends React.Component {
const Collapse = getComponent("Collapse") const Collapse = getComponent("Collapse")
let showSummary = layoutSelectors.showSummary() let showSummary = layoutSelectors.showSummary()
let { docExpansion, displayOperationId } = getConfigs()
return ( return (
<div> <div>
@@ -43,7 +42,7 @@ export default class Operations extends React.Component {
let tagDescription = tagObj.getIn(["tagDetails", "description"], null) let tagDescription = tagObj.getIn(["tagDetails", "description"], null)
let isShownKey = ["operations-tag", tag] let isShownKey = ["operations-tag", tag]
let showTag = layoutSelectors.isShown(isShownKey, true) let showTag = layoutSelectors.isShown(isShownKey, docExpansion === "full" || docExpansion === "list")
return ( return (
<div className={showTag ? "opblock-tag-section is-open" : "opblock-tag-section"} key={"operation-" + tag}> <div className={showTag ? "opblock-tag-section is-open" : "opblock-tag-section"} key={"operation-" + tag}>
@@ -87,6 +86,8 @@ export default class Operations extends React.Component {
request={ request } request={ request }
allowTryItOut={allowTryItOut} allowTryItOut={allowTryItOut}
displayOperationId={displayOperationId}
specActions={ specActions } specActions={ specActions }
specSelectors={ specSelectors } specSelectors={ specSelectors }
@@ -98,6 +99,7 @@ export default class Operations extends React.Component {
getComponent={ getComponent } getComponent={ getComponent }
fn={fn} fn={fn}
getConfigs={ getConfigs }
/> />
}).toArray() }).toArray()
} }

View File

@@ -99,8 +99,7 @@ export default class ParameterRow extends Component {
</td> </td>
<td className="col parameters-col_description"> <td className="col parameters-col_description">
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} <Markdown source={ param.get("description") }/>
source={ param.get("description") }/>
{(isFormData && !isFormDataSupported) && <div>Error: your browser does not support FormData</div>} {(isFormData && !isFormDataSupported) && <div>Error: your browser does not support FormData</div>}
{ bodyParam || !isExecute ? null { bodyParam || !isExecute ? null

View File

@@ -0,0 +1,6 @@
# Providers
Providers are generic bridges to third-party components. They provide two benefits:
1. ability for plugins to override third-party components, because providers are loaded through `getComponent`
2. allows us to avoid painting ourselves into a corner with a third-party component

View File

@@ -0,0 +1,24 @@
import React, { PropTypes } from "react"
import Remarkable from "react-remarkable"
import sanitize from "sanitize-html"
const sanitizeOptions = {
textFilter: function(text) {
return text
.replace(/&quot;/g, "\"")
}
}
function Markdown({ source }) {
const sanitized = sanitize(source, sanitizeOptions)
return <Remarkable
options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}}
source={sanitized}
></Remarkable>
}
Markdown.propTypes = {
source: PropTypes.string.isRequired
}
export default Markdown

View File

@@ -8,7 +8,7 @@ const getExampleComponent = ( sampleResponse, examples, HighlightCode ) => {
let exampleValue let exampleValue
try { try {
exampleValue = example && example.toJS ? example.toJS() : example exampleValue = example && example.toJS ? example.toJS() : example
exampleValue = JSON.stringify(exampleValue) exampleValue = JSON.stringify(exampleValue, null, 2)
} }
catch(e) { catch(e) {
exampleValue = String(example) exampleValue = String(example)
@@ -76,7 +76,7 @@ export default class Response extends React.Component {
<td className="col response-col_description"> <td className="col response-col_description">
<div className="response-col_description__inner"> <div className="response-col_description__inner">
<Markdown options={{html: true, typographer: true, linkify: true, linkTarget: "_blank"}} source={ response.get( "description" ) } /> <Markdown source={ response.get( "description" ) } />
</div> </div>
{ example ? ( { example ? (

View File

@@ -1,3 +1,5 @@
import win from "./window"
export default function curl( request ){ export default function curl( request ){
let curlified = [] let curlified = []
let type = "" let type = ""
@@ -18,11 +20,13 @@ export default function curl( request ){
if ( request.get("body") ){ if ( request.get("body") ){
if(type === "multipart/form-data" && request.get("method") === "POST") { if(type === "multipart/form-data" && request.get("method") === "POST") {
let formDataBody = request.get("body").split("&") for( let [ k,v ] of request.get("body").values()) {
for(var data in formDataBody) {
curlified.push( "-F" ) curlified.push( "-F" )
curlified.push(formDataBody[data]) if (v instanceof win.File) {
curlified.push( `"${k}=@${v.name};type=${v.type}"` )
} else {
curlified.push( `"${k}=${v}"` )
}
} }
} else { } else {
curlified.push( "-d" ) curlified.push( "-d" )

View File

@@ -8,7 +8,7 @@ import { parseSeach, filterConfigs } from "core/utils"
const CONFIGS = [ "url", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion", const CONFIGS = [ "url", "spec", "validatorUrl", "onComplete", "onFailure", "authorizations", "docExpansion",
"apisSorter", "operationsSorter", "supportedSubmitMethods", "dom_id", "defaultModelRendering", "oauth2RedirectUrl", "apisSorter", "operationsSorter", "supportedSubmitMethods", "dom_id", "defaultModelRendering", "oauth2RedirectUrl",
"showRequestHeaders", "custom", "modelPropertyMacro", "parameterMacro" ] "showRequestHeaders", "custom", "modelPropertyMacro", "parameterMacro", "displayOperationId" ]
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const { GIT_DIRTY, GIT_COMMIT, PACKAGE_VERSION } = buildInfo const { GIT_DIRTY, GIT_COMMIT, PACKAGE_VERSION } = buildInfo
@@ -24,9 +24,11 @@ module.exports = function SwaggerUI(opts) {
spec: {}, spec: {},
url: "", url: "",
layout: "BaseLayout", layout: "BaseLayout",
docExpansion: "list",
validatorUrl: "https://online.swagger.io/validator", validatorUrl: "https://online.swagger.io/validator",
configs: {}, configs: {},
custom: {}, custom: {},
displayOperationId: false,
// Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance. // Initial set of plugins ( TODO rename this, or refactor - we don't need presets _and_ plugins. Its just there for performance.
// Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest. // Instead, we can compile the first plugin ( it can be a collection of plugins ), then batch the rest.
@@ -115,6 +117,7 @@ module.exports = function SwaggerUI(opts) {
return downloadSpec() return downloadSpec()
} }
return system
} }
// Add presets // Add presets

View File

@@ -1,6 +1,7 @@
import { fromJS } from "immutable" import { fromJS } from "immutable"
import { fromJSOrdered, validateParam } from "core/utils" import { fromJSOrdered, validateParam } from "core/utils"
import win from "../../window" import win from "../../window"
import findIndex from "lodash/findIndex"
import { import {
UPDATE_SPEC, UPDATE_SPEC,
@@ -41,7 +42,7 @@ export default {
[UPDATE_PARAM]: ( state, {payload} ) => { [UPDATE_PARAM]: ( state, {payload} ) => {
let { path, paramName, value, isXml } = payload let { path, paramName, value, isXml } = payload
return state.updateIn( [ "resolved", "paths", ...path, "parameters" ], fromJS([]), parameters => { return state.updateIn( [ "resolved", "paths", ...path, "parameters" ], fromJS([]), parameters => {
let index = parameters.findIndex( p => p.get( "name" ) === paramName ) const index = findIndex(parameters, p => p.get( "name" ) === paramName )
if (!(value instanceof win.File)) { if (!(value instanceof win.File)) {
value = fromJSOrdered( value ) value = fromJSOrdered( value )
} }

View File

@@ -43,8 +43,6 @@ export const specResolved = createSelector(
// Default Spec ( as an object ) // Default Spec ( as an object )
export const spec = state => { export const spec = state => {
let res = specResolved(state) let res = specResolved(state)
if(res.count() < 1)
res = specJson(state)
return res return res
} }

View File

@@ -46,6 +46,8 @@ import Model from "core/components/model"
import Models from "core/components/models" import Models from "core/components/models"
import TryItOutButton from "core/components/try-it-out-button" import TryItOutButton from "core/components/try-it-out-button"
import Markdown from "core/components/providers/markdown"
import BaseLayout from "core/components/layouts/base" import BaseLayout from "core/components/layouts/base"
import * as LayoutUtils from "core/components/layout-utils" import * as LayoutUtils from "core/components/layout-utils"
@@ -89,6 +91,7 @@ export default function() {
model: Model, model: Model,
models: Models, models: Models,
TryItOutButton, TryItOutButton,
Markdown,
BaseLayout BaseLayout
} }
} }

View File

@@ -1,12 +1,13 @@
import Im from "immutable" import Im from "immutable"
import shallowEqual from "shallowequal"
import camelCase from "lodash/camelCase" import camelCase from "lodash/camelCase"
import upperFirst from "lodash/upperFirst" import upperFirst from "lodash/upperFirst"
import _memoize from "lodash/memoize" import _memoize from "lodash/memoize"
import find from "lodash/find"
import some from "lodash/some" import some from "lodash/some"
import eq from "lodash/eq" import eq from "lodash/eq"
import { memoizedSampleFromSchema, memoizedCreateXMLExample } from "core/plugins/samples/fn" import { memoizedSampleFromSchema, memoizedCreateXMLExample } from "core/plugins/samples/fn"
import win from "./window"
const DEFAULT_REPONSE_KEY = "default" const DEFAULT_REPONSE_KEY = "default"
@@ -34,6 +35,9 @@ export function fromJSOrdered (js) {
if(isImmutable(js)) if(isImmutable(js))
return js // Can't do much here return js // Can't do much here
if (js instanceof win.File)
return js
return !isObject(js) ? js : return !isObject(js) ? js :
Array.isArray(js) ? Array.isArray(js) ?
Im.Seq(js).map(fromJSOrdered).toList() : Im.Seq(js).map(fromJSOrdered).toList() :
@@ -414,11 +418,6 @@ export function pascalCaseFilename(filename) {
return pascalCase(filename.replace(/\.[^./]*$/, "")) return pascalCase(filename.replace(/\.[^./]*$/, ""))
} }
// Only compare a set of props
export function shallowEqualKeys(a,b, keys) {
return !!keys.find(key => !shallowEqual(a[key], b[key]))
}
// Check if ... // Check if ...
// - new props // - new props
// - If immutable, use .is() // - If immutable, use .is()
@@ -589,3 +588,10 @@ export const filterConfigs = (configs, allowed) => {
return filteredConfigs return filteredConfigs
} }
// Is this really required as a helper? Perhaps. TODO: expose the system of presets.apis in docs, so we know what is supported
export const shallowEqualKeys = (a,b, keys) => {
return !!find(keys, (key) => {
return eq(a[key], b[key])
})
}

View File

@@ -3,7 +3,8 @@ function makeWindow() {
location: {}, location: {},
history: {}, history: {},
open: () => {}, open: () => {},
close: () => {} close: () => {},
File: function() {}
} }
if(typeof window === "undefined") { if(typeof window === "undefined") {

2
src/polyfills.js Normal file
View File

@@ -0,0 +1,2 @@
// Promise global, Used ( at least ) by 'whatwg-fetch'. And required by IE 11
require("core-js/fn/promise")

View File

@@ -58,7 +58,7 @@
&.execute &.execute
{ {
animation: pulse 2s infinite; animation: swagger-ui-pulse 2s infinite;
color: #fff; color: #fff;
border-color: #4990e2; border-color: #4990e2;
@@ -66,7 +66,7 @@
} }
@keyframes pulse @keyframes swagger-ui-pulse
{ {
0% 0%
{ {

View File

@@ -209,6 +209,7 @@ body
} }
.opblock-summary-path, .opblock-summary-path,
.opblock-summary-operation-id,
.opblock-summary-path__deprecated .opblock-summary-path__deprecated
{ {
font-size: 16px; font-size: 16px;
@@ -247,6 +248,11 @@ body
text-decoration: line-through; text-decoration: line-through;
} }
.opblock-summary-operation-id
{
font-size: 14px;
}
.opblock-summary-description .opblock-summary-description
{ {
font-size: 13px; font-size: 13px;

View File

@@ -1,8 +1,22 @@
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. # Swagger UI Dist
[![NPM version](https://badge.fury.io/js/swagger-ui-dist.svg)](http://badge.fury.io/js/swagger-ui-dist)
# API
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.
`SwaggerUIBundle` and `SwaggerUIStandalonePreset` can be imported: `SwaggerUIBundle` and `SwaggerUIStandalonePreset` can be imported:
```javascript ```javascript
import { SwaggerUIBundle, SwaggerUIStandalonePreset } from 'swagger-ui-dist' import { SwaggerUIBundle, SwaggerUIStandalonePreset } from "swagger-ui-dist"
```
To get an absolute path to this directory for static file serving, use the exported `getAbsoluteFSPath` method:
```javascript
const swaggerUiAssetPath = require("swagger-ui-dist").getAbsoluteFSPath()
// then instantiate server that serves files from the swaggerUiAssetPath
``` ```
For anything else, check the [Swagger-UI](https://github.com/swagger-api/swagger-ui) repository. For anything else, check the [Swagger-UI](https://github.com/swagger-api/swagger-ui) repository.

View File

@@ -0,0 +1,14 @@
/*
* getAbsoluteFSPath
* @return {string} When run in NodeJS env, returns the absolute path to the current directory
* When run outside of NodeJS, will return an error message
*/
const getAbsoluteFSPath = function () {
// detect whether we are running in a browser or nodejs
if (typeof module !== "undefined" && module.exports) {
return require("path").resolve(__dirname)
}
throw new Error('getAbsoluteFSPath can only be called within a Nodejs environment');
}
module.exports = getAbsoluteFSPath

View File

@@ -1,2 +1,3 @@
module.exports.SwaggerUIBundle = require('./swagger-ui-bundle.js') module.exports.SwaggerUIBundle = require("./swagger-ui-bundle.js")
module.exports.SwaggerUIStandalonePreset = require('./swagger-ui-standalone-preset.js') module.exports.SwaggerUIStandalonePreset = require("./swagger-ui-standalone-preset.js")
module.exports.absolutePath = require("./absolute-path.js")

View File

@@ -0,0 +1,23 @@
/* eslint-env mocha */
import React from "react"
import expect from "expect"
import { render } from "enzyme"
import Markdown from "components/providers/markdown"
describe("UI-3199: Sanitized Markdown causing code examples to be double escaped", function(){
it("should single-escape quotes", function(){
let str = "" +
"This is a test: \n\n" +
" {\"abc\": \"def\"}\n"
let props = {
source: str
}
let el = render(<Markdown {...props}/>)
expect(el.find("code").first().text()).toEqual("{\"abc\": \"def\"}\n")
expect(el.find("code").first().html()).toEqual("{&quot;abc&quot;: &quot;def&quot;}\n")
})
})

View File

@@ -1,6 +1,7 @@
import expect from "expect" import expect from "expect"
import Im from "immutable" import Im from "immutable"
import curl from "core/curlify" import curl from "core/curlify"
import win from "core/window"
describe("curlify", function() { describe("curlify", function() {
@@ -131,12 +132,35 @@ describe("curlify", function() {
url: "http://example.com", url: "http://example.com",
method: "POST", method: "POST",
headers: { "content-type": "multipart/form-data" }, headers: { "content-type": "multipart/form-data" },
body: "id=123&name=Sahar" body: [
["id", "123"],
["name", "Sahar"]
]
} }
let curlified = curl(Im.fromJS(req)) let curlified = curl(Im.fromJS(req))
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F id=123 -F name=Sahar") expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"name=Sahar\"")
})
it("should print a curl with formData and file", function() {
var file = new win.File()
file.name = "file.txt"
file.type = "text/plain"
var req = {
url: "http://example.com",
method: "POST",
headers: { "content-type": "multipart/form-data" },
body: [
["id", "123"],
["file", file]
]
}
let curlified = curl(Im.fromJS(req))
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"file=@file.txt;type=text/plain\"")
}) })
it("prints a curl post statement from an object", function() { it("prints a curl post statement from an object", function() {

View File

@@ -0,0 +1,13 @@
/* eslint-env mocha */
import expect from "expect"
import path from "path"
import getAbsoluteFSPath from "../../swagger-ui-dist-package/absolute-path"
describe("swagger-ui-dist", function(){
describe("getAbsoluteFSPath", function(){
it("returns absolute path", function(){
const expectedPath = path.resolve(__dirname, "../../swagger-ui-dist-package")
expect(getAbsoluteFSPath()).toEqual(expectedPath)
})
})
})

View File

@@ -13,7 +13,7 @@ module.exports = require('./make-webpack-config.js')({
entry: { entry: {
'swagger-ui-bundle': [ 'swagger-ui-bundle': [
'babel-polyfill', './src/polyfills',
'./src/core/index.js' './src/core/index.js'
] ]
}, },

View File

@@ -13,6 +13,7 @@ module.exports = require('./make-webpack-config.js')({
entry: { entry: {
'swagger-ui-standalone-preset': [ 'swagger-ui-standalone-preset': [
'./src/polyfills',
'./src/standalone/index.js' './src/standalone/index.js'
] ]
}, },

View File

@@ -1,9 +1,8 @@
var path = require('path') const path = require("path")
var fs = require('fs') const fs = require("fs")
var node_modules = fs.readdirSync('node_modules').filter(function(x) { return x !== '.bin' }) const nodeModules = fs.readdirSync("node_modules").filter(function(x) { return x !== ".bin" })
module.exports = require("./make-webpack-config.js")({
module.exports = require('./make-webpack-config.js')({
_special: { _special: {
separateStylesheets: true, separateStylesheets: true,
minimize: true, minimize: true,
@@ -15,9 +14,9 @@ module.exports = require('./make-webpack-config.js')({
entry: { entry: {
"swagger-ui": [ "swagger-ui": [
'babel-polyfill', "./src/style/main.scss",
'./src/style/main.scss', "./src/polyfills",
'./src/core/index.js' "./src/core/index.js"
] ]
}, },
@@ -25,11 +24,11 @@ module.exports = require('./make-webpack-config.js')({
// webpack injects some stuff into the resulting file, // webpack injects some stuff into the resulting file,
// these libs need to be pulled in to keep that working. // these libs need to be pulled in to keep that working.
var exceptionsForWebpack = ["ieee754", "base64-js"] var exceptionsForWebpack = ["ieee754", "base64-js"]
if(node_modules.indexOf(request) !== -1 || exceptionsForWebpack.indexOf(request) !== -1) { if(nodeModules.indexOf(request) !== -1 || exceptionsForWebpack.indexOf(request) !== -1) {
cb(null, 'commonjs ' + request) cb(null, "commonjs " + request)
return; return
} }
cb(); cb()
}, },
output: { output: {

View File

@@ -10,12 +10,12 @@ module.exports = require("./make-webpack-config")({
devtool: "eval", devtool: "eval",
entry: { entry: {
'swagger-ui-bundle': [ 'swagger-ui-bundle': [
'webpack/hot/dev-server', './src/polyfills',
'babel-polyfill', './src/core/index.js'
'./src/core/index.js',
], ],
'swagger-ui-standalone-preset': [ 'swagger-ui-standalone-preset': [
'webpack/hot/dev-server', 'webpack/hot/dev-server',
'./src/polyfills',
'./src/standalone/index.js', './src/standalone/index.js',
] ]
}, },