Merge branch 'master' into execute-animation-cpu-usage

This commit is contained in:
kyle
2017-11-03 16:11:30 -07:00
committed by GitHub
48 changed files with 646 additions and 305 deletions

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
.github/pull_request_template.md vendored Normal file
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.

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:

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.4.0 | 2017-10-20 | 2.0, 3.0 | [tag v3.4.0](https://github.com/swagger-api/swagger-ui/tree/v3.4.0)
3.4.2 | 2017-10-30 | 2.0, 3.0 | [tag v3.4.2](https://github.com/swagger-api/swagger-ui/tree/v3.4.2)
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)

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

File diff suppressed because one or more lines are too long

4
dist/swagger-ui.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

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
*/
```
```

View File

@@ -1,6 +1,6 @@
{
"name": "swagger-ui",
"version": "3.4.0",
"version": "3.4.2",
"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.3.0",
"swagger-client": "^3.3.1",
"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": {

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 :

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>

View File

@@ -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>)
}

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
}

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

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 ) {

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>
}
}
}

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

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,9 @@ export default class ResponseBody extends React.Component {
// XML
} else if (/xml/i.test(contentType)) {
body = formatXml(content)
body = formatXml(content, {
textNodesOnSameLine: true
})
bodyEl = <HighlightCode value={ body } />
// HTML or Plain Text

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 {

View File

@@ -20,10 +20,10 @@ function onlyOAS3(selector) {
export const definitionsToAuthorize = onlyOAS3(createSelector(
state,
({ specSelectors }) => {
({specSelectors}) => specSelectors.securityDefinitions(),
(system, definitions) => {
// Coerce our OpenAPI 3.0 definitions into monoflow definitions
// that look like Swagger2 definitions.
let definitions = specSelectors.securityDefinitions()
let list = List()
definitions.entrySeq().forEach( ([ defName, definition ]) => {
@@ -57,4 +57,4 @@ export const definitionsToAuthorize = onlyOAS3(createSelector(
return list
}
))
))

View File

@@ -108,9 +108,6 @@ export default class HttpAuth extends React.Component {
<Row>
<Markdown source={ schema.get("description") } />
</Row>
<Row>
<p>In: <code>{ schema.get("in") }</code></p>
</Row>
<Row>
<label>Value:</label>
{

View File

@@ -48,9 +48,13 @@ 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"]) || Map()
spec => spec.getIn(["components", "securitySchemes"]) || null
))
export const host = OAS3NullSelector

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
}

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"
@@ -52,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"
@@ -106,6 +108,7 @@ export default function() {
ObjectModel,
ArrayModel,
PrimitiveModel,
Property,
TryItOutButton,
Markdown,
BaseLayout,
@@ -122,6 +125,7 @@ export default function() {
}
return [
configsPlugin,
util,
logs,
view,

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>
@@ -722,6 +645,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!

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`

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,
}
}

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,
}
}
}
}

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)
},
}

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])
}

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>

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
{

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,17 +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;
}
}
@@ -77,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);
}
}
@@ -156,7 +154,7 @@
{
svg
{
fill: #444;
fill: $expand-methods-svg-fill-color-hover;
}
}
@@ -164,7 +162,7 @@
{
transition: all .3s;
fill: #777;
fill: $expand-methods-svg-fill-color;
}
}

View File

@@ -27,7 +27,7 @@
small
{
color: #666;
color: $errors-wrapper-errors-small-font-color;
}
}

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 {
@@ -57,9 +57,9 @@ 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;
}
@@ -110,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
@@ -130,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);
}
}
@@ -143,7 +143,7 @@ textarea
transition: opacity .5s;
color: #333;
color: $form-checkbox-label-font-color;
label
{
@@ -179,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;
@@ -192,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;
}
}
}

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);
}
}
}

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,
@@ -377,7 +377,7 @@
margin: 20px 0;
padding: 10px 10px;
border: 2px solid #d8dde7;
border: 2px solid $operational-filter-input-border-color;
}
}
@@ -420,7 +420,7 @@
content: '';
background: rgba(#000,.2);
background: rgba($tab-list-item-first-background-color,.2);
}
}
@@ -525,7 +525,7 @@
{
font-size: 11px;
@include text_code(#999);
@include text_code($response-col-status-undocumented-font-color);
}
}
@@ -541,7 +541,7 @@
{
font-size: 11px;
@include text_code(#999);
@include text_code($response-col-links-font-color);
}
}
@@ -558,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
{
@@ -569,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;
}
}
}
@@ -593,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
@@ -613,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
{
@@ -648,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;
@@ -755,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;
@@ -777,11 +777,11 @@
&.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;
}
}

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;

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;
}

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);
}

View File

@@ -2,7 +2,7 @@
{
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
{
@@ -41,7 +41,7 @@
width: 100%;
margin: 0;
border: 2px solid #547f00;
border: 2px solid $topbar-download-url-wrapper-element-border-color;
border-radius: 4px 0 0 4px;
outline: none;
}
@@ -71,7 +71,7 @@
width: 100%;
border: 2px solid #547f00;
border: 2px solid $topbar-download-url-wrapper-element-border-color;
outline: none;
box-shadow: none;
}
@@ -87,9 +87,9 @@
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);
}
}
}

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;

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;

View File

@@ -16,7 +16,8 @@ import {
fromJSOrdered,
getAcceptControllingResponse,
createDeepLinkPath,
escapeDeepLinkPath
escapeDeepLinkPath,
sanitizeUrl
} from "core/utils"
import win from "core/window"
@@ -885,4 +886,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("")
})
})
})