diff --git a/package.json b/package.json index 50a0a51d..212ccd43 100644 --- a/package.json +++ b/package.json @@ -56,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", @@ -84,6 +84,7 @@ "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": { diff --git a/src/core/components/response-body.jsx b/src/core/components/response-body.jsx index c55c1d6d..e3c2aeb1 100644 --- a/src/core/components/response-body.jsx +++ b/src/core/components/response-body.jsx @@ -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 = // HTML or Plain Text diff --git a/src/core/index.js b/src/core/index.js index abc0ba36..76a0d705 100644 --- a/src/core/index.js +++ b/src/core/index.js @@ -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 { diff --git a/src/core/plugins/oas3/components/http-auth.jsx b/src/core/plugins/oas3/components/http-auth.jsx index bb4727ee..9750f2dd 100644 --- a/src/core/plugins/oas3/components/http-auth.jsx +++ b/src/core/plugins/oas3/components/http-auth.jsx @@ -108,9 +108,6 @@ export default class HttpAuth extends React.Component { - -

In: { schema.get("in") }

-
{ diff --git a/src/core/presets/base.js b/src/core/presets/base.js index ec005b37..b6c11f9f 100644 --- a/src/core/presets/base.js +++ b/src/core/presets/base.js @@ -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" @@ -122,6 +123,7 @@ export default function() { } return [ + configsPlugin, util, logs, view, diff --git a/src/core/utils.js b/src/core/utils.js index b1b7f9de..6ac9eb29 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -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 diff --git a/src/plugins/configs/actions.js b/src/plugins/configs/actions.js new file mode 100644 index 00000000..70588372 --- /dev/null +++ b/src/plugins/configs/actions.js @@ -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, + } +} diff --git a/src/plugins/configs/index.js b/src/plugins/configs/index.js index 2269d873..58edbfa1 100644 --- a/src/plugins/configs/index.js +++ b/src/plugins/configs/index.js @@ -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, + } + } + } } diff --git a/src/plugins/configs/reducers.js b/src/plugins/configs/reducers.js new file mode 100644 index 00000000..5b38931d --- /dev/null +++ b/src/plugins/configs/reducers.js @@ -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) + }, + +} diff --git a/src/plugins/configs/selectors.js b/src/plugins/configs/selectors.js new file mode 100644 index 00000000..dcb6f670 --- /dev/null +++ b/src/plugins/configs/selectors.js @@ -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]) +} diff --git a/test/core/utils.js b/test/core/utils.js index d65046cb..1068aab4 100644 --- a/test/core/utils.js +++ b/test/core/utils.js @@ -925,4 +925,5 @@ sbG8iKTs8L3NjcmlwdD4=`) expect(sanitizeUrl({})).toEqual("") }) }) + })