mirror of
https://github.com/Redocly/redoc.git
synced 2025-07-03 18:53:02 +03:00
chore: add tslint + fix lint issues
This commit is contained in:
parent
3819ad7e6a
commit
dc18743df4
|
@ -5,8 +5,8 @@ import { AppContainer } from 'react-hot-loader';
|
||||||
|
|
||||||
import { Redoc, RedocProps } from '../../src/components/Redoc/Redoc';
|
import { Redoc, RedocProps } from '../../src/components/Redoc/Redoc';
|
||||||
import { AppStore } from '../../src/services/AppStore';
|
import { AppStore } from '../../src/services/AppStore';
|
||||||
import { loadAndBundleSpec } from '../../src/utils/loadAndBundleSpec';
|
|
||||||
import { RedocRawOptions } from '../../src/services/RedocNormalizedOptions';
|
import { RedocRawOptions } from '../../src/services/RedocNormalizedOptions';
|
||||||
|
import { loadAndBundleSpec } from '../../src/utils/loadAndBundleSpec';
|
||||||
|
|
||||||
const renderRoot = (Component: typeof Redoc, props: RedocProps) =>
|
const renderRoot = (Component: typeof Redoc, props: RedocProps) =>
|
||||||
render(
|
render(
|
||||||
|
@ -29,7 +29,7 @@ const options: RedocRawOptions = {};
|
||||||
async function init() {
|
async function init() {
|
||||||
const spec = await loadAndBundleSpec(specUrl);
|
const spec = await loadAndBundleSpec(specUrl);
|
||||||
store = new AppStore(spec, specUrl, options);
|
store = new AppStore(spec, specUrl, options);
|
||||||
renderRoot(Redoc, { store: store });
|
renderRoot(Redoc, { store });
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
@ -44,7 +44,7 @@ if (module.hot) {
|
||||||
store = AppStore.fromJS(state);
|
store = AppStore.fromJS(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRoot(Redoc, { store: store });
|
renderRoot(Redoc, { store });
|
||||||
};
|
};
|
||||||
|
|
||||||
module.hot.accept(['../../src/components/Redoc/Redoc'], reload());
|
module.hot.accept(['../../src/components/Redoc/Redoc'], reload());
|
||||||
|
|
14
package.json
14
package.json
|
@ -7,8 +7,7 @@
|
||||||
"start": "webpack-dev-server --hot",
|
"start": "webpack-dev-server --hot",
|
||||||
"start:perf": "webpack-dev-server --env.prod --env.perf",
|
"start:perf": "webpack-dev-server --env.prod --env.perf",
|
||||||
"start:prod": "webpack-dev-server --env.prod",
|
"start:prod": "webpack-dev-server --env.prod",
|
||||||
"dev": "webpack-dashboard -- webpack-dev-server --hot",
|
"test": "npm run lint && npm run unit && npm run e2e",
|
||||||
"test": "npm run unit && npm run e2e",
|
|
||||||
"unit": "jest",
|
"unit": "jest",
|
||||||
"e2e": "npm run e2e:clean && npm run e2e:tsc && cypress run",
|
"e2e": "npm run e2e:clean && npm run e2e:tsc && cypress run",
|
||||||
"e2e:tsc": "tsc -p tsconfig.e2e.json",
|
"e2e:tsc": "tsc -p tsconfig.e2e.json",
|
||||||
|
@ -20,8 +19,8 @@
|
||||||
"bundle": "npm run bundle:clean && npm run bundle:lib && npm run bundle:standalone",
|
"bundle": "npm run bundle:clean && npm run bundle:lib && npm run bundle:standalone",
|
||||||
"stats": "webpack -p --env.lib --env.standalone --env.prod --json --profile > stats.json",
|
"stats": "webpack -p --env.lib --env.standalone --env.prod --json --profile > stats.json",
|
||||||
"prettier": "prettier --write \"src/**/*.{ts,tsx}\"",
|
"prettier": "prettier --write \"src/**/*.{ts,tsx}\"",
|
||||||
"http-server": "http-server .",
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1",
|
||||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1"
|
"lint": "tslint --project tsconfig.json"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -51,7 +50,6 @@
|
||||||
"enzyme-adapter-react-16": "^1.0.4",
|
"enzyme-adapter-react-16": "^1.0.4",
|
||||||
"enzyme-to-json": "^3.2.2",
|
"enzyme-to-json": "^3.2.2",
|
||||||
"html-webpack-plugin": "^2.30.1",
|
"html-webpack-plugin": "^2.30.1",
|
||||||
"http-server": "^0.10.0",
|
|
||||||
"jest": "^21.1.0",
|
"jest": "^21.1.0",
|
||||||
"mobx-react-devtools": "^4.2.15",
|
"mobx-react-devtools": "^4.2.15",
|
||||||
"prettier": "^1.5.3",
|
"prettier": "^1.5.3",
|
||||||
|
@ -59,14 +57,14 @@
|
||||||
"puppeteer": "^0.10.2",
|
"puppeteer": "^0.10.2",
|
||||||
"raf": "^3.4.0",
|
"raf": "^3.4.0",
|
||||||
"react-dev-utils": "^4.1.0",
|
"react-dev-utils": "^4.1.0",
|
||||||
"react-hot-loader": "3.0.0-beta.6",
|
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2",
|
||||||
"source-map-loader": "^0.2.1",
|
"source-map-loader": "^0.2.1",
|
||||||
"style-loader": "^0.18.2",
|
"style-loader": "^0.18.2",
|
||||||
"ts-jest": "^21.0.1",
|
"ts-jest": "^21.0.1",
|
||||||
"ts-node": "^3.3.0",
|
"ts-node": "^3.3.0",
|
||||||
"tslint": "^5.7.0",
|
"tslint": "^5.7.0",
|
||||||
"typescript": "^2.4.2",
|
"tslint-react": "^3.4.0",
|
||||||
|
"typescript": "^2.6.2",
|
||||||
"webpack": "^3.10.0",
|
"webpack": "^3.10.0",
|
||||||
"webpack-dev-server": "^2.9.5",
|
"webpack-dev-server": "^2.9.5",
|
||||||
"webpack-node-externals": "^1.6.0"
|
"webpack-node-externals": "^1.6.0"
|
||||||
|
@ -84,9 +82,11 @@
|
||||||
"mobx": "^3.3.0",
|
"mobx": "^3.3.0",
|
||||||
"mobx-react": "^4.3.3",
|
"mobx-react": "^4.3.3",
|
||||||
"openapi-sampler": "1.0.0-beta.8",
|
"openapi-sampler": "1.0.0-beta.8",
|
||||||
|
"perfect-scrollbar": "^1.3.0",
|
||||||
"prismjs": "^1.8.1",
|
"prismjs": "^1.8.1",
|
||||||
"prop-types": "^15.6.0",
|
"prop-types": "^15.6.0",
|
||||||
"react-dropdown": "^1.3.0",
|
"react-dropdown": "^1.3.0",
|
||||||
|
"react-hot-loader": "3.0.0-beta.6",
|
||||||
"react-perfect-scrollbar": "^0.2.2",
|
"react-perfect-scrollbar": "^0.2.2",
|
||||||
"react-tabs": "^2.0.0",
|
"react-tabs": "^2.0.0",
|
||||||
"remarkable": "^1.7.1",
|
"remarkable": "^1.7.1",
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
import Dropdown from 'react-dropdown';
|
import Dropdown from 'react-dropdown';
|
||||||
|
|
||||||
import styled from '../styled-components';
|
import styled, { withProps } from '../styled-components';
|
||||||
import { withProps } from '../styled-components';
|
|
||||||
|
|
||||||
export type DropdownOption = { label: string; value: string };
|
export interface DropdownOption {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type DropdownProps = {
|
export interface DropdownProps {
|
||||||
options: DropdownOption[];
|
options: DropdownOption[];
|
||||||
value: DropdownOption;
|
value: DropdownOption;
|
||||||
onChange: (val: DropdownOption) => void;
|
onChange: (val: DropdownOption) => void;
|
||||||
};
|
}
|
||||||
|
|
||||||
export const StyledDropdown = withProps<DropdownProps>(styled(Dropdown))`
|
export const StyledDropdown = withProps<DropdownProps>(styled(Dropdown))`
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import styled from '../styled-components';
|
import styled from '../styled-components';
|
||||||
import { deprecatedCss } from './mixins';
|
|
||||||
import { transparentizeHex } from '../utils/styled';
|
import { transparentizeHex } from '../utils/styled';
|
||||||
|
import { deprecatedCss } from './mixins';
|
||||||
|
|
||||||
export const PropertiesTableCaption = styled.caption`
|
export const PropertiesTableCaption = styled.caption`
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { PropertyNameCell } from './fields-layout';
|
|
||||||
import { transparentizeHex } from '../utils/styled';
|
import { transparentizeHex } from '../utils/styled';
|
||||||
|
import { PropertyNameCell } from './fields-layout';
|
||||||
|
|
||||||
export const ClickablePropertyNameCell = PropertyNameCell.extend`
|
export const ClickablePropertyNameCell = PropertyNameCell.extend`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import styled, { css } from '../styled-components';
|
import styled, { css } from '../styled-components';
|
||||||
|
|
||||||
const headerFontSize = {
|
const headerFontSize = {
|
||||||
'1': '1.85714em',
|
1: '1.85714em',
|
||||||
'2': '1.57143em',
|
2: '1.57143em',
|
||||||
'3': '1.27em',
|
3: '1.27em',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const headerCommonMixin = level => css`
|
export const headerCommonMixin = level => css`
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
|
|
||||||
|
// tslint:disable-next-line
|
||||||
export const linkifyMixin = className => css`
|
export const linkifyMixin = className => css`
|
||||||
${className} {
|
${className} {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -6,7 +6,9 @@ export const deprecatedCss = css`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const hoverColor = color => {
|
export const hoverColor = color => {
|
||||||
if (!color) return '';
|
if (!color) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
return css`
|
return css`
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${color};
|
color: ${color};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import psStyles from 'perfect-scrollbar/css/perfect-scrollbar.css';
|
||||||
import styled, { injectGlobal } from '../styled-components';
|
import styled, { injectGlobal } from '../styled-components';
|
||||||
import psStyles from 'perfect-scrollbar/dist/css/perfect-scrollbar.css';
|
|
||||||
|
|
||||||
import PerfectScrollbarOriginal from 'react-perfect-scrollbar';
|
import PerfectScrollbarOriginal from 'react-perfect-scrollbar';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import styled from '../styled-components';
|
import styled, { withProps } from '../styled-components';
|
||||||
import { withProps } from '../styled-components';
|
|
||||||
|
|
||||||
export const OneOfList = styled.ul`
|
export const OneOfList = styled.ul`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -8,7 +8,7 @@ const directionMap = {
|
||||||
down: '0',
|
down: '0',
|
||||||
};
|
};
|
||||||
|
|
||||||
class _ShelfIcon extends React.PureComponent<{
|
class IntShelfIcon extends React.PureComponent<{
|
||||||
className?: string;
|
className?: string;
|
||||||
float?: 'left' | 'right';
|
float?: 'left' | 'right';
|
||||||
size?: string;
|
size?: string;
|
||||||
|
@ -33,7 +33,7 @@ class _ShelfIcon extends React.PureComponent<{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShelfIcon = styled(_ShelfIcon)`
|
export const ShelfIcon = styled(IntShelfIcon)`
|
||||||
height: ${props => props.size || '18px'};
|
height: ${props => props.size || '18px'};
|
||||||
width: ${props => props.size || '18px'};
|
width: ${props => props.size || '18px'};
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import styled from '../styled-components';
|
|
||||||
import { Tabs as ReactTabs } from 'react-tabs';
|
import { Tabs as ReactTabs } from 'react-tabs';
|
||||||
|
import styled from '../styled-components';
|
||||||
|
|
||||||
export { Tab, TabList, TabPanel } from 'react-tabs';
|
export { Tab, TabList, TabPanel } from 'react-tabs';
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { AppStore } from '../../services/AppStore';
|
import { AppStore } from '../../services/AppStore';
|
||||||
|
|
||||||
import { SecurityDefs } from '../SecuritySchemes/SecuritySchemes';
|
import { DarkRightPanel, MiddlePanel, Row } from '../../common-elements/';
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
import { MiddlePanel, DarkRightPanel, Row } from '../../common-elements/';
|
import { SecurityDefs } from '../SecuritySchemes/SecuritySchemes';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApiHeader,
|
ApiHeader,
|
||||||
DownloadButton,
|
DownloadButton,
|
||||||
InfoSpan,
|
InfoSpan,
|
||||||
InfoSpanBoxWrap,
|
|
||||||
InfoSpanBox,
|
InfoSpanBox,
|
||||||
|
InfoSpanBoxWrap,
|
||||||
} from './styled.elements';
|
} from './styled.elements';
|
||||||
|
|
||||||
interface ApiInfoProps {
|
interface ApiInfoProps {
|
||||||
|
@ -101,8 +101,8 @@ export class ApiInfo extends React.Component<ApiInfoProps> {
|
||||||
components={{
|
components={{
|
||||||
'security-definitions': {
|
'security-definitions': {
|
||||||
component: SecurityDefs,
|
component: SecurityDefs,
|
||||||
propsSelector: store => ({
|
propsSelector: _store => ({
|
||||||
securitySchemes: store!.spec.securitySchemes,
|
securitySchemes: _store!.spec.securitySchemes,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
|
||||||
import { MiddlePanel, H1 } from '../../common-elements';
|
import { H1, MiddlePanel } from '../../common-elements';
|
||||||
|
|
||||||
const delimiterWidth = 15;
|
const delimiterWidth = 15;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { OpenAPIInfo } from '../../types';
|
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { OpenAPIInfo } from '../../types';
|
||||||
import { LogoImgEl, LogoWrap } from './styled.elements';
|
import { LogoImgEl, LogoWrap } from './styled.elements';
|
||||||
|
|
||||||
const LinkWrap = url => Component => <a href={url}>{Component}</a>;
|
const LinkWrap = url => Component => <a href={url}>{Component}</a>;
|
||||||
|
@ -10,7 +10,9 @@ export class ApiLogo extends React.Component<{ info: OpenAPIInfo }> {
|
||||||
render() {
|
render() {
|
||||||
const { info } = this.props;
|
const { info } = this.props;
|
||||||
const logoInfo = info['x-logo'];
|
const logoInfo = info['x-logo'];
|
||||||
if (!logoInfo || !logoInfo.url) return null;
|
if (!logoInfo || !logoInfo.url) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const logo = (
|
const logo = (
|
||||||
<LogoImgEl src={logoInfo.url} style={{ backgroundColor: logoInfo.backgroundColor }} />
|
<LogoImgEl src={logoInfo.url} style={{ backgroundColor: logoInfo.backgroundColor }} />
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { SECTION_ATTR } from '../../services/MenuStore';
|
import { SECTION_ATTR } from '../../services/MenuStore';
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
|
||||||
import { DarkRightPanel, H1, MiddlePanel, ShareLink, Row } from '../../common-elements';
|
import { DarkRightPanel, H1, MiddlePanel, Row, ShareLink } from '../../common-elements';
|
||||||
import { Operation } from '../Operation/Operation';
|
|
||||||
import { ContentItemModel } from '../../services/MenuBuilder';
|
import { ContentItemModel } from '../../services/MenuBuilder';
|
||||||
import { OperationModel } from '../../services/models';
|
import { OperationModel } from '../../services/models';
|
||||||
|
import { Operation } from '../Operation/Operation';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ContentItems extends React.Component<{
|
export class ContentItems extends React.Component<{
|
||||||
|
@ -15,14 +15,16 @@ export class ContentItems extends React.Component<{
|
||||||
}> {
|
}> {
|
||||||
render() {
|
render() {
|
||||||
const items = this.props.items;
|
const items = this.props.items;
|
||||||
if (items.length === 0) return null;
|
if (items.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return items.map(item => <ContentItem item={item} key={item.id} />);
|
return items.map(item => <ContentItem item={item} key={item.id} />);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContentItemProps = {
|
interface ContentItemProps {
|
||||||
item: ContentItemModel;
|
item: ContentItemModel;
|
||||||
};
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ContentItem extends React.Component<ContentItemProps> {
|
export class ContentItem extends React.Component<ContentItemProps> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { MimeLabel, SimpleDropdown, DropdownProps } from '../../common-elements/dropdown';
|
import { DropdownProps, MimeLabel, SimpleDropdown } from '../../common-elements/dropdown';
|
||||||
|
|
||||||
export interface DropdownOrLabelProps extends DropdownProps {
|
export interface DropdownOrLabelProps extends DropdownProps {
|
||||||
Label?: React.ComponentClass;
|
Label?: React.ComponentClass;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { ComponentWithOptions } from '../OptionsProvider';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { OperationModel } from '../../services';
|
|
||||||
import { ShelfIcon } from '../../common-elements';
|
import { ShelfIcon } from '../../common-elements';
|
||||||
|
import { OperationModel } from '../../services';
|
||||||
|
import { ComponentWithOptions } from '../OptionsProvider';
|
||||||
import { SelectOnClick } from '../SelectOnClick/SelectOnClick';
|
import { SelectOnClick } from '../SelectOnClick/SelectOnClick';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
OperationEndpointWrap,
|
|
||||||
EndpointInfo,
|
EndpointInfo,
|
||||||
HttpVerb,
|
HttpVerb,
|
||||||
|
OperationEndpointWrap,
|
||||||
|
ServerItem,
|
||||||
ServerRelativeURL,
|
ServerRelativeURL,
|
||||||
ServersOverlay,
|
ServersOverlay,
|
||||||
ServerItem,
|
|
||||||
ServerUrl,
|
ServerUrl,
|
||||||
} from './styled.elements';
|
} from './styled.elements';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Children } from 'react';
|
|
||||||
import styled from '../styled-components';
|
import styled from '../styled-components';
|
||||||
|
|
||||||
const ErrorWrapper = styled.div`
|
const ErrorWrapper = styled.div`
|
||||||
|
@ -14,7 +13,7 @@ export class ErrorBoundary extends React.Component<{}, { error?: Error }> {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error) {
|
componentDidCatch(error) {
|
||||||
this.setState({ error: error });
|
this.setState({ error });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +34,6 @@ export class ErrorBoundary extends React.Component<{}, { error?: Error }> {
|
||||||
</ErrorWrapper>
|
</ErrorWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Children.only(this.props.children);
|
return React.Children.only(this.props.children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ export interface EnumValuesProps {
|
||||||
export class EnumValues extends React.PureComponent<EnumValuesProps> {
|
export class EnumValues extends React.PureComponent<EnumValuesProps> {
|
||||||
render() {
|
render() {
|
||||||
const { values, type } = this.props;
|
const { values, type } = this.props;
|
||||||
if (!values.length) return null;
|
if (!values.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { FieldDetails } from './FieldDetails';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { FieldDetails } from './FieldDetails';
|
||||||
|
|
||||||
import { ClickablePropertyNameCell, RequiredLabel } from '../../common-elements/fields';
|
import { ClickablePropertyNameCell, RequiredLabel } from '../../common-elements/fields';
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ export interface ConstraintsViewProps {
|
||||||
|
|
||||||
export class ConstraintsView extends React.PureComponent<ConstraintsViewProps> {
|
export class ConstraintsView extends React.PureComponent<ConstraintsViewProps> {
|
||||||
render() {
|
render() {
|
||||||
if (this.props.constraints.length === 0) return null;
|
if (this.props.constraints.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
{' '}
|
{' '}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ExampleValue, FieldLabel } from '../../common-elements/fields';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { ExampleValue, FieldLabel } from '../../common-elements/fields';
|
||||||
|
|
||||||
export interface FieldDetailProps {
|
export interface FieldDetailProps {
|
||||||
value?: any;
|
value?: any;
|
||||||
|
@ -8,7 +8,9 @@ export interface FieldDetailProps {
|
||||||
|
|
||||||
export class FieldDetail extends React.PureComponent<FieldDetailProps> {
|
export class FieldDetail extends React.PureComponent<FieldDetailProps> {
|
||||||
render() {
|
render() {
|
||||||
if (this.props.value === undefined) return null;
|
if (this.props.value === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FieldLabel> {this.props.label} </FieldLabel>{' '}
|
<FieldLabel> {this.props.label} </FieldLabel>{' '}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { FieldProps } from './Field';
|
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
|
||||||
import { EnumValues } from './EnumValues';
|
|
||||||
import { FieldDetail } from './FieldDetail';
|
|
||||||
import { ConstraintsView } from './FieldContstraints';
|
|
||||||
import {
|
import {
|
||||||
RecursiveLabel,
|
|
||||||
NullableLabel,
|
NullableLabel,
|
||||||
PatternLabel,
|
PatternLabel,
|
||||||
|
RecursiveLabel,
|
||||||
TypeFormat,
|
TypeFormat,
|
||||||
TypeName,
|
TypeName,
|
||||||
TypeTitle,
|
|
||||||
TypePrefix,
|
TypePrefix,
|
||||||
|
TypeTitle,
|
||||||
} from '../../common-elements/fields';
|
} from '../../common-elements/fields';
|
||||||
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
import { EnumValues } from './EnumValues';
|
||||||
|
import { FieldProps } from './Field';
|
||||||
|
import { ConstraintsView } from './FieldContstraints';
|
||||||
|
import { FieldDetail } from './FieldDetail';
|
||||||
|
|
||||||
import { Badge } from '../../common-elements/';
|
import { Badge } from '../../common-elements/';
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ class Json extends React.PureComponent<JsonProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
clickListener = (event: MouseEvent) => {
|
clickListener = (event: MouseEvent) => {
|
||||||
var collapsed,
|
let collapsed;
|
||||||
target = event.target as HTMLElement;
|
const target = event.target as HTMLElement;
|
||||||
if (target.className === 'collapser') {
|
if (target.className === 'collapser') {
|
||||||
collapsed = target.parentElement!.getElementsByClassName('collapsible')[0];
|
collapsed = target.parentElement!.getElementsByClassName('collapsible')[0];
|
||||||
if (collapsed.parentElement.classList.contains('collapsed')) {
|
if (collapsed.parentElement.classList.contains('collapsed')) {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
|
||||||
|
import * as DOMPurify from 'dompurify';
|
||||||
import { AppStore, MarkdownRenderer } from '../../services';
|
import { AppStore, MarkdownRenderer } from '../../services';
|
||||||
import { ComponentWithOptions } from '../OptionsProvider';
|
import { ComponentWithOptions } from '../OptionsProvider';
|
||||||
import * as DOMPurify from 'dompurify';
|
|
||||||
|
|
||||||
import { markdownCss } from './styles';
|
import { markdownCss } from './styles';
|
||||||
|
|
||||||
export type MDComponent = {
|
export interface MDComponent {
|
||||||
component: React.ComponentClass;
|
component: React.ComponentClass;
|
||||||
propsSelector: (store?: AppStore) => any;
|
propsSelector: (store?: AppStore) => any;
|
||||||
attrs?: object;
|
attrs?: object;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface MarkdownProps {
|
export interface MarkdownProps {
|
||||||
source: string;
|
source: string;
|
||||||
|
@ -29,7 +29,7 @@ class InternalMarkdown extends ComponentWithOptions<MarkdownProps> {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
if (props.components && props.inline) {
|
if (props.components && props.inline) {
|
||||||
throw new Error(`Markdown Component: "inline" mode doesn't support "components"`);
|
throw new Error('Markdown Component: "inline" mode doesn\'t support "components"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,24 +40,27 @@ class InternalMarkdown extends ComponentWithOptions<MarkdownProps> {
|
||||||
throw new Error('When using components with Markdwon in ReDoc, store prop must be provided');
|
throw new Error('When using components with Markdwon in ReDoc, store prop must be provided');
|
||||||
}
|
}
|
||||||
|
|
||||||
let sanitize: (string) => string;
|
const sanitize =
|
||||||
|
this.props.sanitize || this.options.untrustedSpec
|
||||||
if (this.props.sanitize || this.options.untrustedSpec) {
|
? (html: string) => DOMPurify.sanitize(html)
|
||||||
sanitize = html => DOMPurify.sanitize(html);
|
: (html: string) => html;
|
||||||
} else {
|
|
||||||
sanitize = html => html;
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderer = new MarkdownRenderer();
|
const renderer = new MarkdownRenderer();
|
||||||
const parts = components
|
const parts = components
|
||||||
? renderer.renderMdWithComponents(source, components, raw)
|
? renderer.renderMdWithComponents(source, components, raw)
|
||||||
: [renderer.renderMd(source, raw)];
|
: [renderer.renderMd(source, raw)];
|
||||||
|
|
||||||
if (!parts.length) return null;
|
if (!parts.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let appendClass = ' redoc-markdown';
|
let appendClass = ' redoc-markdown';
|
||||||
if (dense) appendClass += ' -dense';
|
if (dense) {
|
||||||
if (inline) appendClass += ' -inline';
|
appendClass += ' -dense';
|
||||||
|
}
|
||||||
|
if (inline) {
|
||||||
|
appendClass += ' -inline';
|
||||||
|
}
|
||||||
|
|
||||||
if (inline) {
|
if (inline) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { css } from '../../styled-components';
|
|
||||||
import { headerCommonMixin, linkifyMixin } from '../../common-elements';
|
import { headerCommonMixin, linkifyMixin } from '../../common-elements';
|
||||||
|
import { css } from '../../styled-components';
|
||||||
|
|
||||||
export const markdownCss = css`
|
export const markdownCss = css`
|
||||||
p {
|
p {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { MediaContentModel, SchemaModel, MediaTypeModel } from '../../services/models';
|
|
||||||
import { DropdownProps } from '../../common-elements/dropdown';
|
import { DropdownProps } from '../../common-elements/dropdown';
|
||||||
|
import { MediaContentModel, MediaTypeModel, SchemaModel } from '../../services/models';
|
||||||
|
|
||||||
export interface MediaTypeChildProps {
|
export interface MediaTypeChildProps {
|
||||||
schema: SchemaModel;
|
schema: SchemaModel;
|
||||||
|
@ -18,15 +18,19 @@ export interface MediaTypesSwitchProps {
|
||||||
@observer
|
@observer
|
||||||
export class MediaTypesSwitch extends React.Component<MediaTypesSwitchProps> {
|
export class MediaTypesSwitch extends React.Component<MediaTypesSwitchProps> {
|
||||||
switchMedia = ({ value }) => {
|
switchMedia = ({ value }) => {
|
||||||
this.props.content && this.props.content.activate(parseInt(value));
|
if (this.props.content) {
|
||||||
|
this.props.content.activate(parseInt(value, 10));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { content } = this.props;
|
const { content } = this.props;
|
||||||
if (!content || !content.mediaTypes || !content.mediaTypes.length) return null;
|
if (!content || !content.mediaTypes || !content.mediaTypes.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const activeMimeIdx = content.activeMimeIdx;
|
const activeMimeIdx = content.activeMimeIdx;
|
||||||
|
|
||||||
let options = content.mediaTypes.map((mime, idx) => {
|
const options = content.mediaTypes.map((mime, idx) => {
|
||||||
return {
|
return {
|
||||||
label: mime.name,
|
label: mime.name,
|
||||||
value: idx.toString(),
|
value: idx.toString(),
|
||||||
|
|
|
@ -8,13 +8,13 @@ import { Badge, DarkRightPanel, H2, MiddlePanel, Row } from '../../common-elemen
|
||||||
|
|
||||||
import { ComponentWithOptions } from '../OptionsProvider';
|
import { ComponentWithOptions } from '../OptionsProvider';
|
||||||
|
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
|
||||||
import { Parameters } from '../Parameters/Parameters';
|
|
||||||
import { ResponsesList } from '../Responses/ResponsesList';
|
|
||||||
import { RequestSamples } from '../RequestSamples/RequestSamples';
|
|
||||||
import { ResponseSamples } from '../ResponseSamples/ResponseSamples';
|
|
||||||
import { ShareLink } from '../../common-elements/linkify';
|
import { ShareLink } from '../../common-elements/linkify';
|
||||||
import { Endpoint } from '../Endpoint/Endpoint';
|
import { Endpoint } from '../Endpoint/Endpoint';
|
||||||
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
import { Parameters } from '../Parameters/Parameters';
|
||||||
|
import { RequestSamples } from '../RequestSamples/RequestSamples';
|
||||||
|
import { ResponsesList } from '../Responses/ResponsesList';
|
||||||
|
import { ResponseSamples } from '../ResponseSamples/ResponseSamples';
|
||||||
|
|
||||||
import { OperationModel as OperationType } from '../../services/models';
|
import { OperationModel as OperationType } from '../../services/models';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
|
||||||
import * as PropTypes from 'prop-types';
|
import * as PropTypes from 'prop-types';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { RedocNormalizedOptions } from '../services/RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../services/RedocNormalizedOptions';
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
|
import * as React from 'react';
|
||||||
import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel';
|
import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel';
|
||||||
import { ParametersGroup } from './ParametersGroup';
|
import { ParametersGroup } from './ParametersGroup';
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import { UnderlinedHeader } from '../../common-elements';
|
import { UnderlinedHeader } from '../../common-elements';
|
||||||
|
|
||||||
import { Schema } from '../Schema';
|
|
||||||
import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
|
||||||
import { FieldModel, RequestBodyModel } from '../../services/models';
|
import { FieldModel, RequestBodyModel } from '../../services/models';
|
||||||
|
import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
||||||
|
import { Schema } from '../Schema';
|
||||||
|
|
||||||
import { MediaContentModel } from '../../services';
|
import { MediaContentModel } from '../../services';
|
||||||
|
|
||||||
function safePush(obj, prop, item) {
|
function safePush(obj, prop, item) {
|
||||||
if (!obj[prop]) obj[prop] = [];
|
if (!obj[prop]) {
|
||||||
|
obj[prop] = [];
|
||||||
|
}
|
||||||
obj[prop].push(item);
|
obj[prop].push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ const PARAM_PLACES = ['path', 'query', 'cookie', 'header'];
|
||||||
|
|
||||||
export class Parameters extends React.PureComponent<ParametersProps> {
|
export class Parameters extends React.PureComponent<ParametersProps> {
|
||||||
orderParams(params: FieldModel[]): Dict<FieldModel[]> {
|
orderParams(params: FieldModel[]): Dict<FieldModel[]> {
|
||||||
let res = {};
|
const res = {};
|
||||||
params.forEach(param => {
|
params.forEach(param => {
|
||||||
safePush(res, param.in, param);
|
safePush(res, param.in, param);
|
||||||
});
|
});
|
||||||
|
@ -37,7 +39,7 @@ export class Parameters extends React.PureComponent<ParametersProps> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let paramsMap = this.orderParams(parameters);
|
const paramsMap = this.orderParams(parameters);
|
||||||
|
|
||||||
const paramsPlaces = parameters.length > 0 ? PARAM_PLACES : [];
|
const paramsPlaces = parameters.length > 0 ? PARAM_PLACES : [];
|
||||||
|
|
||||||
|
@ -54,17 +56,18 @@ export class Parameters extends React.PureComponent<ParametersProps> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function BodyContent(props: { content: MediaContentModel }): JSX.Element {
|
function DropdownWithinHeader(props) {
|
||||||
const { content } = props;
|
|
||||||
return (
|
return (
|
||||||
<MediaTypesSwitch
|
|
||||||
content={content}
|
|
||||||
renderDropdown={props => (
|
|
||||||
<UnderlinedHeader key="header">
|
<UnderlinedHeader key="header">
|
||||||
Request Body schema: <DropdownOrLabel {...props} />
|
Request Body schema: <DropdownOrLabel {...props} />
|
||||||
</UnderlinedHeader>
|
</UnderlinedHeader>
|
||||||
)}
|
);
|
||||||
>
|
}
|
||||||
|
|
||||||
|
function BodyContent(props: { content: MediaContentModel }): JSX.Element {
|
||||||
|
const { content } = props;
|
||||||
|
return (
|
||||||
|
<MediaTypesSwitch content={content} renderDropdown={DropdownWithinHeader}>
|
||||||
{({ schema }) => {
|
{({ schema }) => {
|
||||||
return <Schema skipReadOnly={true} key="schema" schema={schema} />;
|
return <Schema skipReadOnly={true} key="schema" schema={schema} />;
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -16,7 +16,9 @@ export interface ParametersGroupProps {
|
||||||
export class ParametersGroup extends React.PureComponent<ParametersGroupProps, any> {
|
export class ParametersGroup extends React.PureComponent<ParametersGroupProps, any> {
|
||||||
render() {
|
render() {
|
||||||
const { place, parameters } = this.props;
|
const { place, parameters } = this.props;
|
||||||
if (!parameters || !parameters.length) return null;
|
if (!parameters || !parameters.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={place}>
|
<div key={place}>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { SmallTabs, Tab, TabList, TabPanel } from '../../common-elements';
|
||||||
import { MediaTypeModel } from '../../services/models';
|
import { MediaTypeModel } from '../../services/models';
|
||||||
import { StyledJson } from '../JsonViewer/JsonViewer';
|
import { StyledJson } from '../JsonViewer/JsonViewer';
|
||||||
import { SourceCode } from '../SourceCode/SourceCode';
|
import { SourceCode } from '../SourceCode/SourceCode';
|
||||||
import { SmallTabs, TabList, TabPanel, Tab } from '../../common-elements';
|
|
||||||
import { NoSampleLabel } from './styled.elements';
|
import { NoSampleLabel } from './styled.elements';
|
||||||
|
|
||||||
import { isJsonLike, langFromMime } from '../../utils';
|
import { isJsonLike, langFromMime } from '../../utils';
|
||||||
|
@ -24,7 +24,9 @@ export class MediaTypeSamples extends React.Component<PayloadSamplesProps> {
|
||||||
(sample && <SourceCode lang={langFromMime(mimeType)} source={sample} />) || { noSample };
|
(sample && <SourceCode lang={langFromMime(mimeType)} source={sample} />) || { noSample };
|
||||||
|
|
||||||
const examplesNames = Object.keys(examples);
|
const examplesNames = Object.keys(examples);
|
||||||
if (examplesNames.length === 0) return noSample;
|
if (examplesNames.length === 0) {
|
||||||
|
return noSample;
|
||||||
|
}
|
||||||
if (examplesNames.length > 1) {
|
if (examplesNames.length > 1) {
|
||||||
return (
|
return (
|
||||||
<SmallTabs>
|
<SmallTabs>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { MediaTypeSamples } from './MediaTypeSamples';
|
|
||||||
import * as React from 'react'
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { MediaTypeSamples } from './MediaTypeSamples';
|
||||||
|
|
||||||
import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
||||||
|
|
||||||
|
@ -16,15 +16,18 @@ export interface PayloadSamplesProps {
|
||||||
export class PayloadSamples extends React.Component<PayloadSamplesProps> {
|
export class PayloadSamples extends React.Component<PayloadSamplesProps> {
|
||||||
render() {
|
render() {
|
||||||
const mimeContent = this.props.content;
|
const mimeContent = this.props.content;
|
||||||
if (mimeContent === undefined) return null;
|
if (mimeContent === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MediaTypesSwitch
|
<MediaTypesSwitch content={mimeContent} renderDropdown={this.renderDropdown}>
|
||||||
content={mimeContent}
|
|
||||||
renderDropdown={props => <DropdownOrLabel Label={MimeLabel} Dropdown={InvertedSimpleDropdown} {...props} />}
|
|
||||||
>
|
|
||||||
{mediaType => <MediaTypeSamples key="samples" mediaType={mediaType} />}
|
{mediaType => <MediaTypeSamples key="samples" mediaType={mediaType} />}
|
||||||
</MediaTypesSwitch>
|
</MediaTypesSwitch>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderDropdown = props => {
|
||||||
|
return <DropdownOrLabel Label={MimeLabel} Dropdown={InvertedSimpleDropdown} {...props} />;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ export const InvertedSimpleDropdown = styled(SimpleDropdown)`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
export const NoSampleLabel = styled.div`
|
export const NoSampleLabel = styled.div`
|
||||||
font-family: ${props => props.theme.code.fontFamily};
|
font-family: ${props => props.theme.code.fontFamily};
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import * as React from 'react';
|
|
||||||
import * as PropTypes from 'prop-types';
|
import * as PropTypes from 'prop-types';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ThemeProvider } from '../../styled-components';
|
import { ThemeProvider } from '../../styled-components';
|
||||||
|
|
||||||
import { ApiInfo } from '../ApiInfo/ApiInfo';
|
|
||||||
import { RedocWrap, ApiContent } from './elements';
|
|
||||||
import { ApiLogo } from '../ApiLogo/ApiLogo';
|
|
||||||
import { SideMenu } from '../SideMenu/SideMenu';
|
|
||||||
import { ContentItems } from '../ContentItems/ContentItems';
|
|
||||||
import { AppStore } from '../../services';
|
import { AppStore } from '../../services';
|
||||||
|
import { ApiInfo } from '../ApiInfo/ApiInfo';
|
||||||
|
import { ApiLogo } from '../ApiLogo/ApiLogo';
|
||||||
|
import { ContentItems } from '../ContentItems/ContentItems';
|
||||||
import { OptionsProvider } from '../OptionsProvider';
|
import { OptionsProvider } from '../OptionsProvider';
|
||||||
|
import { SideMenu } from '../SideMenu/SideMenu';
|
||||||
import { StickySidebar } from '../StickySidebar/StickySidebar';
|
import { StickySidebar } from '../StickySidebar/StickySidebar';
|
||||||
|
import { ApiContent, RedocWrap } from './elements';
|
||||||
|
|
||||||
export interface RedocProps {
|
export interface RedocProps {
|
||||||
store: AppStore;
|
store: AppStore;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import * as React from 'react';
|
|
||||||
import * as PropTypes from 'prop-types';
|
import * as PropTypes from 'prop-types';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { Loading } from './Loading/Loading';
|
|
||||||
import { StoreProvider } from './StoreProvider';
|
|
||||||
import { ErrorBoundary } from './ErrorBoundary';
|
|
||||||
import { Redoc } from './Redoc/Redoc';
|
|
||||||
import { RedocNormalizedOptions, RedocRawOptions } from '../services/RedocNormalizedOptions';
|
import { RedocNormalizedOptions, RedocRawOptions } from '../services/RedocNormalizedOptions';
|
||||||
|
import { ErrorBoundary } from './ErrorBoundary';
|
||||||
|
import { Loading } from './Loading/Loading';
|
||||||
|
import { Redoc } from './Redoc/Redoc';
|
||||||
|
import { StoreProvider } from './StoreProvider';
|
||||||
|
|
||||||
export interface RedocStandaloneProps {
|
export interface RedocStandaloneProps {
|
||||||
spec?: object;
|
spec?: object;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { SourceCode } from '../SourceCode/SourceCode';
|
|
||||||
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
import { OperationModel } from '../../services/models';
|
import { OperationModel } from '../../services/models';
|
||||||
|
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
||||||
|
import { SourceCode } from '../SourceCode/SourceCode';
|
||||||
|
|
||||||
import { Tab, Tabs, TabList, TabPanel } from '../../common-elements';
|
import { Tab, TabList, TabPanel, Tabs } from '../../common-elements';
|
||||||
|
|
||||||
export interface RequestSamplesProps {
|
export interface RequestSamplesProps {
|
||||||
operation: OperationModel;
|
operation: OperationModel;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { MediaContentModel, OperationModel } from '../../services/models';
|
import { MediaContentModel, OperationModel } from '../../services/models';
|
||||||
|
|
||||||
import { Tab, Tabs, TabList, TabPanel } from '../../common-elements';
|
import { Tab, TabList, TabPanel, Tabs } from '../../common-elements';
|
||||||
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
||||||
|
|
||||||
export interface ResponseSampleProps {
|
export interface ResponseSampleProps {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { ResponseModel } from '../../services/models';
|
import { ResponseModel } from '../../services/models';
|
||||||
|
|
||||||
import { UnderlinedHeader } from '../../common-elements';
|
import { UnderlinedHeader } from '../../common-elements';
|
||||||
import { Schema } from '../Schema';
|
|
||||||
import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
|
||||||
import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel';
|
import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel';
|
||||||
|
import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch';
|
||||||
|
import { Schema } from '../Schema';
|
||||||
|
|
||||||
import { ResponseHeaders } from './ResponseHeaders';
|
import { ResponseHeaders } from './ResponseHeaders';
|
||||||
import { ResponseDetailsWrap, StyledResponseTitle } from './styled.elements';
|
import { ResponseDetailsWrap, StyledResponseTitle } from './styled.elements';
|
||||||
|
@ -38,14 +38,7 @@ export class ResponseView extends React.Component<{ response: ResponseModel }> {
|
||||||
!empty && (
|
!empty && (
|
||||||
<ResponseDetailsWrap>
|
<ResponseDetailsWrap>
|
||||||
<ResponseHeaders headers={headers} />
|
<ResponseHeaders headers={headers} />
|
||||||
<MediaTypesSwitch
|
<MediaTypesSwitch content={content} renderDropdown={this.renderDropdown}>
|
||||||
content={content}
|
|
||||||
renderDropdown={props => (
|
|
||||||
<UnderlinedHeader key="header">
|
|
||||||
Response Schema: <DropdownOrLabel {...props} />
|
|
||||||
</UnderlinedHeader>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{({ schema }) => {
|
{({ schema }) => {
|
||||||
return <Schema skipWriteOnly={true} key="schema" schema={schema} />;
|
return <Schema skipWriteOnly={true} key="schema" schema={schema} />;
|
||||||
}}
|
}}
|
||||||
|
@ -55,4 +48,12 @@ export class ResponseView extends React.Component<{ response: ResponseModel }> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderDropdown = props => {
|
||||||
|
return (
|
||||||
|
<UnderlinedHeader key="header">
|
||||||
|
Response Schema: <DropdownOrLabel {...props} />
|
||||||
|
</UnderlinedHeader>
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { PropertiesTable } from '../../common-elements/fields-layout';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { PropertiesTable } from '../../common-elements/fields-layout';
|
||||||
|
|
||||||
import { HeadersCaption } from './styled.elements';
|
|
||||||
import { mapWithLast } from '../../utils';
|
|
||||||
import { FieldModel } from '../../services/models';
|
import { FieldModel } from '../../services/models';
|
||||||
|
import { mapWithLast } from '../../utils';
|
||||||
import { Field } from '../Fields/Field';
|
import { Field } from '../Fields/Field';
|
||||||
|
import { HeadersCaption } from './styled.elements';
|
||||||
|
|
||||||
export interface ResponseHeadersProps {
|
export interface ResponseHeadersProps {
|
||||||
headers?: FieldModel[];
|
headers?: FieldModel[];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
|
||||||
import { ShelfIcon } from '../../common-elements';
|
import { ShelfIcon } from '../../common-elements';
|
||||||
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
|
||||||
export interface ResponseTitleProps {
|
export interface ResponseTitleProps {
|
||||||
code: string;
|
code: string;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { ResponseView } from './Response';
|
|
||||||
import { ResponseModel } from '../../services/models';
|
import { ResponseModel } from '../../services/models';
|
||||||
|
import { ResponseView } from './Response';
|
||||||
|
|
||||||
const ResponsesHeader = styled.h3`
|
const ResponsesHeader = styled.h3`
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
@ -19,7 +19,9 @@ export class ResponsesList extends React.PureComponent<ResponseListProps> {
|
||||||
render() {
|
render() {
|
||||||
const { responses } = this.props;
|
const { responses } = this.props;
|
||||||
|
|
||||||
if (!responses || responses.length === 0) return null;
|
if (!responses || responses.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
|
||||||
import { ResponseTitle } from './ResponseTitle';
|
|
||||||
import { UnderlinedHeader } from '../../common-elements';
|
import { UnderlinedHeader } from '../../common-elements';
|
||||||
import { transparentizeHex } from '../../utils';
|
import { transparentizeHex } from '../../utils';
|
||||||
|
import { ResponseTitle } from './ResponseTitle';
|
||||||
|
|
||||||
export const StyledResponseTitle = styled(ResponseTitle)`
|
export const StyledResponseTitle = styled(ResponseTitle)`
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { SchemaProps, Schema } from './Schema';
|
import { Schema, SchemaProps } from './Schema';
|
||||||
|
|
||||||
import { ArrayOpenningLabel, ArrayClosingLabel } from '../../common-elements';
|
import { ArrayClosingLabel, ArrayOpenningLabel } from '../../common-elements';
|
||||||
|
|
||||||
export class ArraySchema extends React.PureComponent<SchemaProps> {
|
export class ArraySchema extends React.PureComponent<SchemaProps> {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { StyledDropdown, DropdownOption } from '../../common-elements/dropdown';
|
import { DropdownOption, StyledDropdown } from '../../common-elements/dropdown';
|
||||||
import { SchemaModel } from '../../services/models';
|
import { SchemaModel } from '../../services/models';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
|
@ -10,7 +10,9 @@ export class DiscriminatorDropdown extends React.Component<{
|
||||||
enumValues: string[];
|
enumValues: string[];
|
||||||
}> {
|
}> {
|
||||||
sortOptions(options: DropdownOption[], enumValues: string[]): void {
|
sortOptions(options: DropdownOption[], enumValues: string[]): void {
|
||||||
if (enumValues.length === 0) return;
|
if (enumValues.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const enumOrder = {};
|
const enumOrder = {};
|
||||||
|
|
||||||
|
@ -48,7 +50,7 @@ export class DiscriminatorDropdown extends React.Component<{
|
||||||
}
|
}
|
||||||
|
|
||||||
changeActiveChild = ({ value }) => {
|
changeActiveChild = ({ value }) => {
|
||||||
const idx = parseInt(value);
|
const idx = parseInt(value, 10);
|
||||||
this.props.parent.activateOneOf(idx);
|
this.props.parent.activateOneOf(idx);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { SchemaModel, FieldModel } from '../../services/models';
|
import { FieldModel, SchemaModel } from '../../services/models';
|
||||||
|
|
||||||
import { Field } from '../Fields/Field';
|
|
||||||
import { DiscriminatorDropdown } from './DiscriminatorDropdown';
|
|
||||||
import { Schema, SchemaProps } from './Schema';
|
|
||||||
import {
|
import {
|
||||||
InnerPropertiesWrap,
|
InnerPropertiesWrap,
|
||||||
PropertiesTable,
|
PropertiesTable,
|
||||||
PropertiesTableCaption,
|
PropertiesTableCaption,
|
||||||
PropertyCellWithInner,
|
PropertyCellWithInner,
|
||||||
} from '../../common-elements/fields-layout';
|
} from '../../common-elements/fields-layout';
|
||||||
|
import { Field } from '../Fields/Field';
|
||||||
|
import { DiscriminatorDropdown } from './DiscriminatorDropdown';
|
||||||
|
import { Schema, SchemaProps } from './Schema';
|
||||||
|
|
||||||
import { mapWithLast } from '../../utils';
|
import { mapWithLast } from '../../utils';
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,33 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { OneOfButton, OneOfLabel, OneOfList } from '../../common-elements/schema';
|
import {
|
||||||
import { SchemaProps, Schema } from './Schema';
|
OneOfButton as StyledOneOfButton,
|
||||||
|
OneOfLabel,
|
||||||
|
OneOfList,
|
||||||
|
} from '../../common-elements/schema';
|
||||||
|
import { SchemaModel } from '../../services/models';
|
||||||
|
import { Schema, SchemaProps } from './Schema';
|
||||||
|
|
||||||
|
export interface OneOfButtonProps {
|
||||||
|
subSchema: SchemaModel;
|
||||||
|
idx: number;
|
||||||
|
schema: SchemaModel;
|
||||||
|
}
|
||||||
|
export class OneOfButton extends React.PureComponent<OneOfButtonProps> {
|
||||||
|
render() {
|
||||||
|
const { idx, schema, subSchema } = this.props;
|
||||||
|
return (
|
||||||
|
<StyledOneOfButton active={idx === schema.activeOneOf} onClick={this.activateOneOf}>
|
||||||
|
{subSchema.title || subSchema.displayType}
|
||||||
|
</StyledOneOfButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
activateOneOf() {
|
||||||
|
this.props.schema.activateOneOf(this.props.idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class OneOfSchema extends React.Component<SchemaProps> {
|
export class OneOfSchema extends React.Component<SchemaProps> {
|
||||||
|
@ -17,13 +42,7 @@ export class OneOfSchema extends React.Component<SchemaProps> {
|
||||||
<OneOfLabel> {schema.oneOfType} </OneOfLabel>
|
<OneOfLabel> {schema.oneOfType} </OneOfLabel>
|
||||||
<OneOfList>
|
<OneOfList>
|
||||||
{oneOf.map((subSchema, idx) => (
|
{oneOf.map((subSchema, idx) => (
|
||||||
<OneOfButton
|
<OneOfButton key={subSchema._$ref} schema={schema} subSchema={subSchema} idx={idx} />
|
||||||
key={subSchema._$ref}
|
|
||||||
active={idx === schema.activeOneOf}
|
|
||||||
onClick={() => schema.activateOneOf(idx)}
|
|
||||||
>
|
|
||||||
{subSchema.title || subSchema.displayType}
|
|
||||||
</OneOfButton>
|
|
||||||
))}
|
))}
|
||||||
</OneOfList>
|
</OneOfList>
|
||||||
<Schema schema={oneOf[schema.activeOneOf]} />
|
<Schema schema={oneOf[schema.activeOneOf]} />
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { FieldDetails } from '../Fields/FieldDetails';
|
|
||||||
import { RecursiveLabel, TypeName, TypeTitle } from '../../common-elements/fields';
|
import { RecursiveLabel, TypeName, TypeTitle } from '../../common-elements/fields';
|
||||||
|
import { FieldDetails } from '../Fields/FieldDetails';
|
||||||
|
|
||||||
import { SchemaModel } from '../../services/models';
|
import { SchemaModel } from '../../services/models';
|
||||||
|
|
||||||
|
import { ArraySchema } from './ArraySchema';
|
||||||
import { ObjectSchema } from './ObjectSchema';
|
import { ObjectSchema } from './ObjectSchema';
|
||||||
import { OneOfSchema } from './OneOfSchema';
|
import { OneOfSchema } from './OneOfSchema';
|
||||||
import { ArraySchema } from './ArraySchema';
|
|
||||||
|
|
||||||
export interface SchemaProps {
|
export interface SchemaProps {
|
||||||
schema: SchemaModel;
|
schema: SchemaModel;
|
||||||
|
@ -21,7 +21,9 @@ export interface SchemaProps {
|
||||||
export class Schema extends React.Component<Partial<SchemaProps>> {
|
export class Schema extends React.Component<Partial<SchemaProps>> {
|
||||||
render() {
|
render() {
|
||||||
const { schema } = this.props;
|
const { schema } = this.props;
|
||||||
if (!schema) return <em> Schema not provided </em>;
|
if (!schema) {
|
||||||
|
return <em> Schema not provided </em>;
|
||||||
|
}
|
||||||
const { type, oneOf, discriminatorProp, isCircular } = schema;
|
const { type, oneOf, discriminatorProp, isCircular } = schema;
|
||||||
|
|
||||||
if (isCircular) {
|
if (isCircular) {
|
||||||
|
|
|
@ -2,8 +2,8 @@ import * as React from 'react';
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
import { transparentizeHex } from '../../utils/styled';
|
import { transparentizeHex } from '../../utils/styled';
|
||||||
|
|
||||||
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
|
||||||
import { UnderlinedHeader } from '../../common-elements/headers';
|
import { UnderlinedHeader } from '../../common-elements/headers';
|
||||||
|
import { SecurityRequirementModel } from '../../services/models/SecurityRequirement';
|
||||||
|
|
||||||
const ScopeName = styled.code`
|
const ScopeName = styled.code`
|
||||||
font-size: ${props => props.theme.code.fontSize};
|
font-size: ${props => props.theme.code.fontSize};
|
||||||
|
@ -57,7 +57,9 @@ export interface SecurityRequirementsProps {
|
||||||
export class SecurityRequirements extends React.PureComponent<SecurityRequirementsProps> {
|
export class SecurityRequirements extends React.PureComponent<SecurityRequirementsProps> {
|
||||||
render() {
|
render() {
|
||||||
const securities = this.props.securities;
|
const securities = this.props.securities;
|
||||||
if (!securities.length) return null;
|
if (!securities.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AuthHeaderColumn>
|
<AuthHeaderColumn>
|
||||||
|
|
|
@ -2,10 +2,10 @@ import * as React from 'react';
|
||||||
|
|
||||||
import { SecuritySchemesModel } from '../../services/models';
|
import { SecuritySchemesModel } from '../../services/models';
|
||||||
|
|
||||||
import styled from '../../styled-components';
|
|
||||||
import { H2, ShareLink } from '../../common-elements';
|
import { H2, ShareLink } from '../../common-elements';
|
||||||
import { Markdown } from '../Markdown/Markdown';
|
import styled from '../../styled-components';
|
||||||
import { OpenAPISecurityScheme } from '../../types';
|
import { OpenAPISecurityScheme } from '../../types';
|
||||||
|
import { Markdown } from '../Markdown/Markdown';
|
||||||
|
|
||||||
const AUTH_TYPES = {
|
const AUTH_TYPES = {
|
||||||
oauth2: 'OAuth2',
|
oauth2: 'OAuth2',
|
||||||
|
@ -76,7 +76,9 @@ export interface SecurityDefsProps {
|
||||||
|
|
||||||
export class SecurityDefs extends React.PureComponent<SecurityDefsProps> {
|
export class SecurityDefs extends React.PureComponent<SecurityDefsProps> {
|
||||||
render() {
|
render() {
|
||||||
if (!this.props.securitySchemes) return null;
|
if (!this.props.securitySchemes) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import * as React from 'react';
|
||||||
import { ClipboardService } from '../../services';
|
import { ClipboardService } from '../../services';
|
||||||
|
|
||||||
export class SelectOnClick extends React.PureComponent {
|
export class SelectOnClick extends React.PureComponent {
|
||||||
|
private child: HTMLDivElement | null;
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
ClipboardService.selectElement(this.refs.child);
|
ClipboardService.selectElement(this.refs.child);
|
||||||
};
|
};
|
||||||
|
@ -10,7 +11,7 @@ export class SelectOnClick extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props;
|
const { children } = this.props;
|
||||||
return (
|
return (
|
||||||
<div ref="child" onClick={this.handleClick}>
|
<div ref={el => (this.child = el)} onClick={this.handleClick}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { IMenuItem, OperationModel } from '../../services';
|
|
||||||
import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements';
|
|
||||||
import { ShelfIcon } from '../../common-elements/shelfs';
|
import { ShelfIcon } from '../../common-elements/shelfs';
|
||||||
|
import { IMenuItem, OperationModel } from '../../services';
|
||||||
import { MenuItems } from './MenuItems';
|
import { MenuItems } from './MenuItems';
|
||||||
|
import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements';
|
||||||
|
|
||||||
interface MenuItemProps {
|
interface MenuItemProps {
|
||||||
item: IMenuItem;
|
item: IMenuItem;
|
||||||
|
@ -42,9 +42,9 @@ export class MenuItem extends React.Component<MenuItemProps> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OperationMenuItemContentProps = {
|
export interface OperationMenuItemContentProps {
|
||||||
item: OperationModel;
|
item: OperationModel;
|
||||||
};
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class OperationMenuItemContent extends React.Component<OperationMenuItemContentProps> {
|
class OperationMenuItemContent extends React.Component<OperationMenuItemContentProps> {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
import { IMenuItem } from '../../services';
|
import { IMenuItem } from '../../services';
|
||||||
|
|
||||||
import { MenuItemUl } from './styled.elements';
|
|
||||||
import { MenuItem } from './MenuItem';
|
import { MenuItem } from './MenuItem';
|
||||||
|
import { MenuItemUl } from './styled.elements';
|
||||||
|
|
||||||
interface MenuItemsProps {
|
interface MenuItemsProps {
|
||||||
items: IMenuItem[];
|
items: IMenuItem[];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { ComponentWithOptions } from '../OptionsProvider';
|
|
||||||
import * as React from 'react';
|
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { ComponentWithOptions } from '../OptionsProvider';
|
||||||
|
|
||||||
import { MenuStore, IMenuItem } from '../../services/MenuStore';
|
import { IMenuItem, MenuStore } from '../../services/MenuStore';
|
||||||
import { MenuItems } from './MenuItems';
|
import { MenuItems } from './MenuItems';
|
||||||
|
|
||||||
import { PerfectScrollbar } from '../../common-elements/perfect-scrollbar';
|
import { PerfectScrollbar } from '../../common-elements/perfect-scrollbar';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { deprecatedCss } from '../../common-elements';
|
import { deprecatedCss } from '../../common-elements';
|
||||||
import styled, { withProps, css } from '../../styled-components';
|
import styled, { css, withProps } from '../../styled-components';
|
||||||
|
|
||||||
export const OperationBadge = withProps<{ type: string }>(styled.span).attrs({
|
export const OperationBadge = withProps<{ type: string }>(styled.span).attrs({
|
||||||
className: props => `operation-type ${props.type}`,
|
className: props => `operation-type ${props.type}`,
|
||||||
|
@ -88,7 +88,7 @@ export const MenuItemLi = withProps<{ depth: number }>(styled.li)`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const menuItemDepth = {
|
export const menuItemDepth = {
|
||||||
'0': css`
|
0: css`
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
|
@ -96,14 +96,14 @@ export const menuItemDepth = {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
color: ${props => props.theme.colors.text};
|
color: ${props => props.theme.colors.text};
|
||||||
`,
|
`,
|
||||||
'1': css`
|
1: css`
|
||||||
font-size: 0.929em;
|
font-size: 0.929em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${props => props.theme.colors.main};
|
color: ${props => props.theme.colors.main};
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
'2': css`
|
2: css`
|
||||||
color: ${props => props.theme.colors.text};
|
color: ${props => props.theme.colors.text};
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { highlight } from '../../utils';
|
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
import { highlight } from '../../utils';
|
||||||
|
|
||||||
const StyledPre = styled.pre`
|
const StyledPre = styled.pre`
|
||||||
font-family: ${props => props.theme.code.fontFamily};
|
font-family: ${props => props.theme.code.fontFamily};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ComponentWithOptions } from '../OptionsProvider';
|
|
||||||
import { RedocNormalizedOptions, RedocRawOptions } from '../../services/RedocNormalizedOptions';
|
import { RedocNormalizedOptions, RedocRawOptions } from '../../services/RedocNormalizedOptions';
|
||||||
import styled from '../../styled-components';
|
import styled from '../../styled-components';
|
||||||
|
import { ComponentWithOptions } from '../OptionsProvider';
|
||||||
|
|
||||||
let Stickyfill;
|
let Stickyfill;
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
|
@ -34,11 +34,15 @@ export class StickySidebar extends ComponentWithOptions<StickySidebarProps> {
|
||||||
stickyElement: Element;
|
stickyElement: Element;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
stickyfill && stickyfill.add(this.stickyElement);
|
if (stickyfill) {
|
||||||
|
stickyfill.add(this.stickyElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
stickyfill && stickyfill.remove(this.stickyElement);
|
if (stickyfill) {
|
||||||
|
stickyfill.remove(this.stickyElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get scrollYOffset() {
|
get scrollYOffset() {
|
||||||
|
@ -52,7 +56,7 @@ export class StickySidebar extends ComponentWithOptions<StickySidebarProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let top = this.scrollYOffset;
|
const top = this.scrollYOffset;
|
||||||
|
|
||||||
const height = `calc(100vh - ${top})`;
|
const height = `calc(100vh - ${top})`;
|
||||||
|
|
||||||
|
@ -60,6 +64,7 @@ export class StickySidebar extends ComponentWithOptions<StickySidebarProps> {
|
||||||
<StyledStickySidebar
|
<StyledStickySidebar
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
style={{ top, height }}
|
style={{ top, height }}
|
||||||
|
// tslint:disable-next-line
|
||||||
innerRef={el => {
|
innerRef={el => {
|
||||||
this.stickyElement = el;
|
this.stickyElement = el;
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
|
|
||||||
import { AppStore } from '../services/';
|
import { AppStore } from '../services/';
|
||||||
import { loadAndBundleSpec } from '../utils';
|
|
||||||
import { RedocRawOptions } from '../services/RedocNormalizedOptions';
|
import { RedocRawOptions } from '../services/RedocNormalizedOptions';
|
||||||
|
import { loadAndBundleSpec } from '../utils';
|
||||||
|
|
||||||
interface StoreProviderProps {
|
interface StoreProviderProps {
|
||||||
specUrl?: string;
|
specUrl?: string;
|
||||||
|
@ -36,7 +36,7 @@ export class StoreProvider extends Component<StoreProviderProps, StoreProviderSt
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
let { specUrl, spec, options } = this.props;
|
const { specUrl, spec, options } = this.props;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: true,
|
loading: true,
|
||||||
|
@ -62,7 +62,9 @@ export class StoreProvider extends Component<StoreProviderProps, StoreProviderSt
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.error) throw this.state.error;
|
if (this.state.error) {
|
||||||
|
throw this.state.error;
|
||||||
|
}
|
||||||
return this.props.children(this.state);
|
return this.props.children(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { OpenAPISpec } from '../types';
|
import { OpenAPISpec } from '../types';
|
||||||
import { SpecStore } from './models';
|
|
||||||
import { MenuStore } from './MenuStore';
|
|
||||||
import { ScrollService } from './ScrollService';
|
|
||||||
import { loadAndBundleSpec } from '../utils/loadAndBundleSpec';
|
import { loadAndBundleSpec } from '../utils/loadAndBundleSpec';
|
||||||
|
import { MenuStore } from './MenuStore';
|
||||||
|
import { SpecStore } from './models';
|
||||||
import { RedocNormalizedOptions, RedocRawOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions, RedocRawOptions } from './RedocNormalizedOptions';
|
||||||
|
import { ScrollService } from './ScrollService';
|
||||||
|
|
||||||
type StoreData = {
|
interface StoreData {
|
||||||
menu: {
|
menu: {
|
||||||
activeItemIdx: number;
|
activeItemIdx: number;
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ type StoreData = {
|
||||||
data: any;
|
data: any;
|
||||||
};
|
};
|
||||||
options: RedocRawOptions;
|
options: RedocRawOptions;
|
||||||
};
|
}
|
||||||
|
|
||||||
export async function createStore(
|
export async function createStore(
|
||||||
spec: object,
|
spec: object,
|
||||||
|
@ -26,6 +26,18 @@ export async function createStore(
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AppStore {
|
export class AppStore {
|
||||||
|
/**
|
||||||
|
* deserialize store
|
||||||
|
* **SUPER HACKY AND NOT OPTIMAL IMPLEMENTATION**
|
||||||
|
*/
|
||||||
|
// TODO:
|
||||||
|
static fromJS(state: StoreData): AppStore {
|
||||||
|
const inst = new AppStore(state.spec.data, state.spec.url, state.options);
|
||||||
|
inst.menu.activeItemIdx = state.menu.activeItemIdx || 0;
|
||||||
|
inst.menu.activate(inst.menu.flatItems[inst.menu.activeItemIdx]);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
menu: MenuStore;
|
menu: MenuStore;
|
||||||
spec: SpecStore;
|
spec: SpecStore;
|
||||||
rawOptions: RedocRawOptions;
|
rawOptions: RedocRawOptions;
|
||||||
|
@ -63,15 +75,4 @@ export class AppStore {
|
||||||
options: this.rawOptions,
|
options: this.rawOptions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* deserialize store
|
|
||||||
* **SUPER HACKY AND NOT OPTIMAL IMPLEMENTATION**
|
|
||||||
*/
|
|
||||||
// TODO:
|
|
||||||
static fromJS(state: StoreData): AppStore {
|
|
||||||
const inst = new AppStore(state.spec.data, state.spec.url, state.options);
|
|
||||||
inst.menu.activeItemIdx = state.menu.activeItemIdx || 0;
|
|
||||||
inst.menu.activate(inst.menu.flatItems[inst.menu.activeItemIdx]);
|
|
||||||
return inst;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ export class ClipboardService {
|
||||||
static selectElement(element: any): void {
|
static selectElement(element: any): void {
|
||||||
let range;
|
let range;
|
||||||
let selection;
|
let selection;
|
||||||
if ((<any>document.body).createTextRange) {
|
if ((document.body as any).createTextRange) {
|
||||||
range = (<any>document.body).createTextRange();
|
range = (document.body as any).createTextRange();
|
||||||
range.moveToElementText(element);
|
range.moveToElementText(element);
|
||||||
range.select();
|
range.select();
|
||||||
} else if (document.createRange && window.getSelection) {
|
} else if (document.createRange && window.getSelection) {
|
||||||
|
@ -25,8 +25,8 @@ export class ClipboardService {
|
||||||
}
|
}
|
||||||
|
|
||||||
static deselect(): void {
|
static deselect(): void {
|
||||||
if ((<any>document).selection) {
|
if ((document as any).selection) {
|
||||||
(<any>document).selection.empty();
|
(document as any).selection.empty();
|
||||||
} else if (window.getSelection) {
|
} else if (window.getSelection) {
|
||||||
window.getSelection().removeAllRanges();
|
window.getSelection().removeAllRanges();
|
||||||
}
|
}
|
||||||
|
@ -44,13 +44,15 @@ export class ClipboardService {
|
||||||
|
|
||||||
static copyElement(element: any): boolean {
|
static copyElement(element: any): boolean {
|
||||||
ClipboardService.selectElement(element);
|
ClipboardService.selectElement(element);
|
||||||
let res = ClipboardService.copySelected();
|
const res = ClipboardService.copySelected();
|
||||||
if (res) ClipboardService.deselect();
|
if (res) {
|
||||||
|
ClipboardService.deselect();
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static copyCustom(text: string): boolean {
|
static copyCustom(text: string): boolean {
|
||||||
let textArea = document.createElement('textarea');
|
const textArea = document.createElement('textarea');
|
||||||
textArea.style.position = 'fixed';
|
textArea.style.position = 'fixed';
|
||||||
textArea.style.top = '0';
|
textArea.style.top = '0';
|
||||||
textArea.style.left = '0';
|
textArea.style.left = '0';
|
||||||
|
@ -77,7 +79,7 @@ export class ClipboardService {
|
||||||
|
|
||||||
textArea.select();
|
textArea.select();
|
||||||
|
|
||||||
let res = ClipboardService.copySelected();
|
const res = ClipboardService.copySelected();
|
||||||
|
|
||||||
document.body.removeChild(textArea);
|
document.body.removeChild(textArea);
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -8,7 +8,7 @@ function isSameHash(a: string, b: string): boolean {
|
||||||
return a === b || '#' + a === b || a === '#' + b;
|
return a === b || '#' + a === b || a === '#' + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HistoryService {
|
class IntHistoryService {
|
||||||
private causedHashChange: boolean = false;
|
private causedHashChange: boolean = false;
|
||||||
private _emiter;
|
private _emiter;
|
||||||
|
|
||||||
|
@ -50,7 +50,9 @@ class _HistoryService {
|
||||||
@bind
|
@bind
|
||||||
@debounce
|
@debounce
|
||||||
update(hash: string | null, rewriteHistory: boolean = false) {
|
update(hash: string | null, rewriteHistory: boolean = false) {
|
||||||
if (hash == null || isSameHash(hash, this.hash)) return;
|
if (hash == null || isSameHash(hash, this.hash)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (rewriteHistory) {
|
if (rewriteHistory) {
|
||||||
if (isBrowser) {
|
if (isBrowser) {
|
||||||
window.history.replaceState(null, '', window.location.href.split('#')[0] + '#' + hash);
|
window.history.replaceState(null, '', window.location.href.split('#')[0] + '#' + hash);
|
||||||
|
@ -64,7 +66,7 @@ class _HistoryService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HistoryService = new _HistoryService();
|
export const HistoryService = new IntHistoryService();
|
||||||
|
|
||||||
if (module.hot) {
|
if (module.hot) {
|
||||||
module.hot.dispose(() => {
|
module.hot.dispose(() => {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as Remarkable from 'remarkable';
|
import * as Remarkable from 'remarkable';
|
||||||
|
|
||||||
import { MDComponent } from '../components/Markdown/Markdown';
|
import { MDComponent } from '../components/Markdown/Markdown';
|
||||||
|
import { highlight, html2Str } from '../utils';
|
||||||
import { IMenuItem, SECTION_ATTR } from './MenuStore';
|
import { IMenuItem, SECTION_ATTR } from './MenuStore';
|
||||||
import { GroupModel } from './models';
|
import { GroupModel } from './models';
|
||||||
import { highlight, html2Str } from '../utils';
|
|
||||||
|
|
||||||
const md = new Remarkable('default', {
|
const md = new Remarkable('default', {
|
||||||
html: true,
|
html: true,
|
||||||
|
@ -20,14 +20,14 @@ export function buildComponentComment(name: string) {
|
||||||
return `<!-- ReDoc-Inject: <${name}> -->`;
|
return `<!-- ReDoc-Inject: <${name}> -->`;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MarkdownHeading = {
|
interface MarkdownHeading {
|
||||||
name: string;
|
name: string;
|
||||||
children?: MarkdownHeading[];
|
children?: MarkdownHeading[];
|
||||||
content?: string;
|
content?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export class MarkdownRenderer {
|
export class MarkdownRenderer {
|
||||||
public headings: GroupModel[] = [];
|
headings: GroupModel[] = [];
|
||||||
currentTopHeading: GroupModel;
|
currentTopHeading: GroupModel;
|
||||||
|
|
||||||
private _origRules: any = {};
|
private _origRules: any = {};
|
||||||
|
@ -52,9 +52,11 @@ export class MarkdownRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
flattenHeadings(container?: MarkdownHeading[]): MarkdownHeading[] {
|
flattenHeadings(container?: MarkdownHeading[]): MarkdownHeading[] {
|
||||||
if (container === undefined) return [];
|
if (container === undefined) {
|
||||||
let res: MarkdownHeading[] = [];
|
return [];
|
||||||
for (let heading of container) {
|
}
|
||||||
|
const res: MarkdownHeading[] = [];
|
||||||
|
for (const heading of container) {
|
||||||
res.push(heading);
|
res.push(heading);
|
||||||
res.push(...this.flattenHeadings(heading.children));
|
res.push(...this.flattenHeadings(heading.children));
|
||||||
}
|
}
|
||||||
|
@ -64,14 +66,16 @@ export class MarkdownRenderer {
|
||||||
attachHeadingsContent(rawText: string) {
|
attachHeadingsContent(rawText: string) {
|
||||||
const buildRegexp = heading => new RegExp(`<h\\d ${SECTION_ATTR}="section/${heading.id}">`);
|
const buildRegexp = heading => new RegExp(`<h\\d ${SECTION_ATTR}="section/${heading.id}">`);
|
||||||
|
|
||||||
let flatHeadings = this.flattenHeadings(this.headings);
|
const flatHeadings = this.flattenHeadings(this.headings);
|
||||||
if (flatHeadings.length < 1) return;
|
if (flatHeadings.length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let prevHeading = flatHeadings[0];
|
let prevHeading = flatHeadings[0];
|
||||||
|
|
||||||
let prevPos = rawText.search(buildRegexp(prevHeading));
|
let prevPos = rawText.search(buildRegexp(prevHeading));
|
||||||
for (let i = 1; i < flatHeadings.length; i++) {
|
for (let i = 1; i < flatHeadings.length; i++) {
|
||||||
let heading = flatHeadings[i];
|
const heading = flatHeadings[i];
|
||||||
let currentPos = rawText.substr(prevPos + 1).search(buildRegexp(heading)) + prevPos + 1;
|
const currentPos = rawText.substr(prevPos + 1).search(buildRegexp(heading)) + prevPos + 1;
|
||||||
prevHeading.content = html2Str(rawText.substring(prevPos, currentPos));
|
prevHeading.content = html2Str(rawText.substring(prevPos, currentPos));
|
||||||
|
|
||||||
prevHeading = heading;
|
prevHeading = heading;
|
||||||
|
@ -84,17 +88,17 @@ export class MarkdownRenderer {
|
||||||
if (tokens[idx].hLevel > 2) {
|
if (tokens[idx].hLevel > 2) {
|
||||||
return this._origRules.open(tokens, idx);
|
return this._origRules.open(tokens, idx);
|
||||||
} else {
|
} else {
|
||||||
let content = tokens[idx + 1].content;
|
const content = tokens[idx + 1].content;
|
||||||
if (tokens[idx].hLevel === 1) {
|
if (tokens[idx].hLevel === 1) {
|
||||||
this.currentTopHeading = this.saveHeading(content);
|
this.currentTopHeading = this.saveHeading(content);
|
||||||
let id = this.currentTopHeading.id;
|
const id = this.currentTopHeading.id;
|
||||||
return (
|
return (
|
||||||
`<a name="${id}"></a>` +
|
`<a name="${id}"></a>` +
|
||||||
`<h${tokens[idx].hLevel} ${SECTION_ATTR}="${id}" id="${id}">` +
|
`<h${tokens[idx].hLevel} ${SECTION_ATTR}="${id}" id="${id}">` +
|
||||||
`<a class="share-link" href="#${id}"></a>`
|
`<a class="share-link" href="#${id}"></a>`
|
||||||
);
|
);
|
||||||
} else if (tokens[idx].hLevel === 2) {
|
} else if (tokens[idx].hLevel === 2) {
|
||||||
let { id } = this.saveHeading(content, this.currentTopHeading.items);
|
const { id } = this.saveHeading(content, this.currentTopHeading.items);
|
||||||
return (
|
return (
|
||||||
`<a name="${id}"></a>` +
|
`<a name="${id}"></a>` +
|
||||||
`<h${tokens[idx].hLevel} ${SECTION_ATTR}="${id}" id="${id}">` +
|
`<h${tokens[idx].hLevel} ${SECTION_ATTR}="${id}" id="${id}">` +
|
||||||
|
@ -119,9 +123,9 @@ export class MarkdownRenderer {
|
||||||
md.renderer.rules.heading_close = this.headingCloseRule;
|
md.renderer.rules.heading_close = this.headingCloseRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = rawText;
|
const text = rawText;
|
||||||
|
|
||||||
let res = md.render(text);
|
const res = md.render(text);
|
||||||
|
|
||||||
this.attachHeadingsContent(res);
|
this.attachHeadingsContent(res);
|
||||||
|
|
||||||
|
@ -142,17 +146,18 @@ export class MarkdownRenderer {
|
||||||
rawText: string,
|
rawText: string,
|
||||||
components: Dict<MDComponent>,
|
components: Dict<MDComponent>,
|
||||||
raw: boolean = true,
|
raw: boolean = true,
|
||||||
): (string | MDComponent)[] {
|
): Array<string | MDComponent> {
|
||||||
let componentDefs: string[] = [];
|
const componentDefs: string[] = [];
|
||||||
let match;
|
const anyCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '(.*?)'), 'gmi');
|
||||||
let anyCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '(.*?)'), 'gmi');
|
let match = anyCompRegexp.exec(rawText);
|
||||||
while ((match = anyCompRegexp.exec(rawText))) {
|
while (match) {
|
||||||
componentDefs.push(match[1]);
|
componentDefs.push(match[1]);
|
||||||
|
match = anyCompRegexp.exec(rawText);
|
||||||
}
|
}
|
||||||
|
|
||||||
let splitCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '.*?'), 'mi');
|
const splitCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '.*?'), 'mi');
|
||||||
let htmlParts = rawText.split(splitCompRegexp);
|
const htmlParts = rawText.split(splitCompRegexp);
|
||||||
let res: any[] = [];
|
const res: any[] = [];
|
||||||
for (let i = 0; i < htmlParts.length; i++) {
|
for (let i = 0; i < htmlParts.length; i++) {
|
||||||
const htmlPart = htmlParts[i];
|
const htmlPart = htmlParts[i];
|
||||||
if (htmlPart) {
|
if (htmlPart) {
|
||||||
|
@ -160,10 +165,12 @@ export class MarkdownRenderer {
|
||||||
}
|
}
|
||||||
if (componentDefs[i]) {
|
if (componentDefs[i]) {
|
||||||
const { componentName, attrs } = parseComponent(componentDefs[i]);
|
const { componentName, attrs } = parseComponent(componentDefs[i]);
|
||||||
if (!componentName) continue;
|
if (!componentName) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
res.push({
|
res.push({
|
||||||
...components[componentName],
|
...components[componentName],
|
||||||
attrs: attrs,
|
attrs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +185,9 @@ function parseComponent(
|
||||||
attrs: any;
|
attrs: any;
|
||||||
} {
|
} {
|
||||||
const match = /<([\w_-]+).*?>/.exec(htmlTag);
|
const match = /<([\w_-]+).*?>/.exec(htmlTag);
|
||||||
if (match === null || match.length <= 1) return { componentName: undefined, attrs: {} };
|
if (match === null || match.length <= 1) {
|
||||||
|
return { componentName: undefined, attrs: {} };
|
||||||
|
}
|
||||||
const componentName = match[1];
|
const componentName = match[1];
|
||||||
return {
|
return {
|
||||||
componentName,
|
componentName,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { OpenAPIParser } from './OpenAPIParser';
|
|
||||||
import { GroupModel, OperationModel } from './models';
|
|
||||||
import { JsonPointer, isOperationName } from '../utils';
|
|
||||||
import { OpenAPIOperation, OpenAPIParameter, OpenAPISpec, OpenAPITag, Referenced } from '../types';
|
import { OpenAPIOperation, OpenAPIParameter, OpenAPISpec, OpenAPITag, Referenced } from '../types';
|
||||||
|
import { isOperationName, JsonPointer } from '../utils';
|
||||||
import { MarkdownRenderer } from './MarkdownRenderer';
|
import { MarkdownRenderer } from './MarkdownRenderer';
|
||||||
|
import { GroupModel, OperationModel } from './models';
|
||||||
|
import { OpenAPIParser } from './OpenAPIParser';
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
|
|
||||||
export type TagInfo = OpenAPITag & {
|
export type TagInfo = OpenAPITag & {
|
||||||
|
@ -13,7 +13,7 @@ export type TagInfo = OpenAPITag & {
|
||||||
export type ExtendedOpenAPIOperation = {
|
export type ExtendedOpenAPIOperation = {
|
||||||
_$ref: string;
|
_$ref: string;
|
||||||
httpVerb: string;
|
httpVerb: string;
|
||||||
pathParameters: Referenced<OpenAPIParameter>[];
|
pathParameters: Array<Referenced<OpenAPIParameter>>;
|
||||||
} & OpenAPIOperation;
|
} & OpenAPIOperation;
|
||||||
|
|
||||||
export type TagsInfoMap = Dict<TagInfo>;
|
export type TagsInfoMap = Dict<TagInfo>;
|
||||||
|
@ -70,9 +70,9 @@ export class MenuBuilder {
|
||||||
tags: TagsInfoMap,
|
tags: TagsInfoMap,
|
||||||
options: RedocNormalizedOptions,
|
options: RedocNormalizedOptions,
|
||||||
): GroupModel[] {
|
): GroupModel[] {
|
||||||
let res: GroupModel[] = [];
|
const res: GroupModel[] = [];
|
||||||
for (let group of groups) {
|
for (const group of groups) {
|
||||||
let item = new GroupModel('group', group, parent);
|
const item = new GroupModel('group', group, parent);
|
||||||
item.depth = GROUP_DEPTH;
|
item.depth = GROUP_DEPTH;
|
||||||
item.items = MenuBuilder.getTagsItems(parser, tags, item, group, options);
|
item.items = MenuBuilder.getTagsItems(parser, tags, item, group, options);
|
||||||
res.push(item);
|
res.push(item);
|
||||||
|
@ -111,16 +111,18 @@ export class MenuBuilder {
|
||||||
return tagsMap[tagName];
|
return tagsMap[tagName];
|
||||||
});
|
});
|
||||||
|
|
||||||
let res: (GroupModel | OperationModel)[] = [];
|
const res: Array<GroupModel | OperationModel> = [];
|
||||||
for (let tag of tags) {
|
for (const tag of tags) {
|
||||||
if (!tag) continue;
|
if (!tag) {
|
||||||
let item = new GroupModel('tag', tag, parent);
|
continue;
|
||||||
|
}
|
||||||
|
const item = new GroupModel('tag', tag, parent);
|
||||||
item.depth = GROUP_DEPTH + 1;
|
item.depth = GROUP_DEPTH + 1;
|
||||||
item.items = this.getOperationsItems(parser, item, tag, item.depth + 1, options);
|
item.items = this.getOperationsItems(parser, item, tag, item.depth + 1, options);
|
||||||
|
|
||||||
// don't put empty tag into content, instead put its operations
|
// don't put empty tag into content, instead put its operations
|
||||||
if (tag.name === '') {
|
if (tag.name === '') {
|
||||||
let items = this.getOperationsItems(parser, undefined, tag, item.depth + 1, options);
|
const items = this.getOperationsItems(parser, undefined, tag, item.depth + 1, options);
|
||||||
res.push(...items);
|
res.push(...items);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -147,9 +149,9 @@ export class MenuBuilder {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let res: OperationModel[] = [];
|
const res: OperationModel[] = [];
|
||||||
for (let operationInfo of tag.operations) {
|
for (const operationInfo of tag.operations) {
|
||||||
let operation = new OperationModel(parser, operationInfo, parent, options);
|
const operation = new OperationModel(parser, operationInfo, parent, options);
|
||||||
operation.depth = depth;
|
operation.depth = depth;
|
||||||
res.push(operation);
|
res.push(operation);
|
||||||
}
|
}
|
||||||
|
@ -161,16 +163,15 @@ export class MenuBuilder {
|
||||||
*/
|
*/
|
||||||
static getTagsWithOperations(spec: OpenAPISpec): TagsInfoMap {
|
static getTagsWithOperations(spec: OpenAPISpec): TagsInfoMap {
|
||||||
const tags: TagsInfoMap = {};
|
const tags: TagsInfoMap = {};
|
||||||
for (let tag of spec.tags || []) {
|
for (const tag of spec.tags || []) {
|
||||||
tags[tag.name] = Object.assign(tag);
|
tags[tag.name] = { ...tag, operations: [] };
|
||||||
tags[tag.name].operations = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const paths = spec.paths;
|
const paths = spec.paths;
|
||||||
for (let pathName of Object.keys(paths)) {
|
for (const pathName of Object.keys(paths)) {
|
||||||
const path = paths[pathName];
|
const path = paths[pathName];
|
||||||
const operations = Object.keys(path).filter(isOperationName);
|
const operations = Object.keys(path).filter(isOperationName);
|
||||||
for (let operationName of operations) {
|
for (const operationName of operations) {
|
||||||
const operationInfo = path[operationName];
|
const operationInfo = path[operationName];
|
||||||
let operationTags = operationInfo.tags;
|
let operationTags = operationInfo.tags;
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ export class MenuBuilder {
|
||||||
operationTags = [''];
|
operationTags = [''];
|
||||||
}
|
}
|
||||||
const operationPointer = JsonPointer.compile(['paths', pathName, operationName]);
|
const operationPointer = JsonPointer.compile(['paths', pathName, operationName]);
|
||||||
for (let tagName of operationTags) {
|
for (const tagName of operationTags) {
|
||||||
let tag = tags[tagName];
|
let tag = tags[tagName];
|
||||||
if (tag === undefined) {
|
if (tag === undefined) {
|
||||||
tag = {
|
tag = {
|
||||||
|
@ -188,7 +189,9 @@ export class MenuBuilder {
|
||||||
};
|
};
|
||||||
tags[tagName] = tag;
|
tags[tagName] = tag;
|
||||||
}
|
}
|
||||||
if (tag['x-traitTag']) continue;
|
if (tag['x-traitTag']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
tag.operations.push({
|
tag.operations.push({
|
||||||
...operationInfo,
|
...operationInfo,
|
||||||
_$ref: operationPointer,
|
_$ref: operationPointer,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
import { action, computed } from 'mobx';
|
||||||
import { querySelector } from '../utils/dom';
|
import { querySelector } from '../utils/dom';
|
||||||
import { OperationModel, GroupModel, SpecStore } from './models';
|
import { GroupModel, OperationModel, SpecStore } from './models';
|
||||||
import { computed, action } from 'mobx';
|
|
||||||
|
|
||||||
import { ScrollService } from './ScrollService';
|
|
||||||
import { HistoryService } from './HistoryService';
|
import { HistoryService } from './HistoryService';
|
||||||
|
import { ScrollService } from './ScrollService';
|
||||||
|
|
||||||
import { GROUP_DEPTH } from './MenuBuilder';
|
|
||||||
import { flattenByProp } from '../utils';
|
import { flattenByProp } from '../utils';
|
||||||
|
import { GROUP_DEPTH } from './MenuBuilder';
|
||||||
|
|
||||||
export type MenuItemGroupType = 'group' | 'tag' | 'section';
|
export type MenuItemGroupType = 'group' | 'tag' | 'section';
|
||||||
export type MenuItemType = MenuItemGroupType | 'operation';
|
export type MenuItemType = MenuItemGroupType | 'operation';
|
||||||
|
@ -18,7 +18,7 @@ export interface IMenuItem {
|
||||||
name: string;
|
name: string;
|
||||||
depth: number;
|
depth: number;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
items: Array<IMenuItem>;
|
items: IMenuItem[];
|
||||||
parent?: IMenuItem;
|
parent?: IMenuItem;
|
||||||
deprecated?: boolean;
|
deprecated?: boolean;
|
||||||
type: MenuItemType;
|
type: MenuItemType;
|
||||||
|
@ -34,18 +34,18 @@ export const SECTION_ATTR = 'data-section-id';
|
||||||
* Stores all side-menu related information
|
* Stores all side-menu related information
|
||||||
*/
|
*/
|
||||||
export class MenuStore {
|
export class MenuStore {
|
||||||
/**
|
|
||||||
* cached flattened menu items to support absolute indexing
|
|
||||||
*/
|
|
||||||
private _unsubscribe: Function;
|
|
||||||
private _hashUnsubscribe: Function;
|
|
||||||
private _items?: (GroupModel | OperationModel)[];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* active item absolute index (when flattened). -1 means nothing is selected
|
* active item absolute index (when flattened). -1 means nothing is selected
|
||||||
*/
|
*/
|
||||||
activeItemIdx: number = -1;
|
activeItemIdx: number = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cached flattened menu items to support absolute indexing
|
||||||
|
*/
|
||||||
|
private _unsubscribe: () => void;
|
||||||
|
private _hashUnsubscribe: () => void;
|
||||||
|
private _items?: Array<GroupModel | OperationModel>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param spec [SpecStore](#SpecStore) which contains page content structure
|
* @param spec [SpecStore](#SpecStore) which contains page content structure
|
||||||
|
@ -107,13 +107,15 @@ export class MenuStore {
|
||||||
*/
|
*/
|
||||||
@action.bound
|
@action.bound
|
||||||
updateOnHash(hash: string = HistoryService.hash): boolean {
|
updateOnHash(hash: string = HistoryService.hash): boolean {
|
||||||
if (!hash) return false;
|
if (!hash) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let item: IMenuItem | undefined;
|
let item: IMenuItem | undefined;
|
||||||
hash = hash.substr(1);
|
hash = hash.substr(1);
|
||||||
let namespace = hash.split('/')[0];
|
const namespace = hash.split('/')[0];
|
||||||
let ptr = decodeURIComponent(hash.substr(namespace.length + 1));
|
let ptr = decodeURIComponent(hash.substr(namespace.length + 1));
|
||||||
if (namespace === 'section' || namespace === 'tag') {
|
if (namespace === 'section' || namespace === 'tag') {
|
||||||
let sectionId = ptr.split('/')[0];
|
const sectionId = ptr.split('/')[0];
|
||||||
ptr = ptr.substr(sectionId.length);
|
ptr = ptr.substr(sectionId.length);
|
||||||
|
|
||||||
let searchId;
|
let searchId;
|
||||||
|
@ -123,14 +125,14 @@ export class MenuStore {
|
||||||
searchId = ptr || namespace + '/' + sectionId;
|
searchId = ptr || namespace + '/' + sectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
item = this.flatItems.find(item => item.id === searchId);
|
item = this.flatItems.find(i => i.id === searchId);
|
||||||
if (item === undefined) {
|
if (item === undefined) {
|
||||||
this._scrollService.scrollIntoViewBySelector(`[${SECTION_ATTR}="${searchId}"]`);
|
this._scrollService.scrollIntoViewBySelector(`[${SECTION_ATTR}="${searchId}"]`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (namespace === 'operation') {
|
} else if (namespace === 'operation') {
|
||||||
item = this.flatItems.find(item => {
|
item = this.flatItems.find(i => {
|
||||||
return (item as OperationModel).operationId === ptr;
|
return (i as OperationModel).operationId === ptr;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (item) {
|
if (item) {
|
||||||
|
@ -219,7 +221,11 @@ export class MenuStore {
|
||||||
* @see MenuStore.activate
|
* @see MenuStore.activate
|
||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
activateAndScroll(item: IMenuItem | undefined, updateHash: boolean, rewriteHistory?: boolean) {
|
activateAndScroll(
|
||||||
|
item: IMenuItem | undefined,
|
||||||
|
updateHash: boolean,
|
||||||
|
rewriteHistory?: boolean,
|
||||||
|
) {
|
||||||
this.activate(item, updateHash, rewriteHistory);
|
this.activate(item, updateHash, rewriteHistory);
|
||||||
this.scrollToActive();
|
this.scrollToActive();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ import { resolve as urlResolve } from 'url';
|
||||||
|
|
||||||
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
|
import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types';
|
||||||
|
|
||||||
|
import { appendToMdHeading, isBrowser } from '../utils/';
|
||||||
import { JsonPointer } from '../utils/JsonPointer';
|
import { JsonPointer } from '../utils/JsonPointer';
|
||||||
import { isNamedDefinition } from '../utils/openapi';
|
import { isNamedDefinition } from '../utils/openapi';
|
||||||
import { COMPONENT_REGEXP, buildComponentComment } from './MarkdownRenderer';
|
import { buildComponentComment, COMPONENT_REGEXP } from './MarkdownRenderer';
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
import { appendToMdHeading, isBrowser } from '../utils/';
|
|
||||||
|
|
||||||
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
||||||
* endless recursion because of circular refs
|
* endless recursion because of circular refs
|
||||||
*/
|
*/
|
||||||
class RefCounter {
|
class RefCounter {
|
||||||
public _counter = {};
|
_counter = {};
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this._counter = {};
|
this._counter = {};
|
||||||
|
@ -42,6 +42,8 @@ export class OpenAPIParser {
|
||||||
@observable specUrl: string;
|
@observable specUrl: string;
|
||||||
@observable.ref spec: OpenAPISpec;
|
@observable.ref spec: OpenAPISpec;
|
||||||
|
|
||||||
|
private _refCounter: RefCounter = new RefCounter();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
spec: OpenAPISpec,
|
spec: OpenAPISpec,
|
||||||
specUrl: string | undefined,
|
specUrl: string | undefined,
|
||||||
|
@ -60,8 +62,6 @@ export class OpenAPIParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _refCounter: RefCounter = new RefCounter();
|
|
||||||
|
|
||||||
validate(spec: any) {
|
validate(spec: any) {
|
||||||
if (spec.openapi === undefined) {
|
if (spec.openapi === undefined) {
|
||||||
throw new Error('Document must be valid OpenAPI 3.0.0 definition');
|
throw new Error('Document must be valid OpenAPI 3.0.0 definition');
|
||||||
|
@ -93,8 +93,12 @@ export class OpenAPIParser {
|
||||||
*/
|
*/
|
||||||
byRef = <T extends any = any>(ref: string): T | undefined => {
|
byRef = <T extends any = any>(ref: string): T | undefined => {
|
||||||
let res;
|
let res;
|
||||||
if (this.spec === undefined) return;
|
if (!this.spec) {
|
||||||
if (ref.charAt(0) !== '#') ref = '#' + ref;
|
return;
|
||||||
|
}
|
||||||
|
if (ref.charAt(0) !== '#') {
|
||||||
|
ref = '#' + ref;
|
||||||
|
}
|
||||||
ref = decodeURIComponent(ref);
|
ref = decodeURIComponent(ref);
|
||||||
try {
|
try {
|
||||||
res = JsonPointer.get(this.spec, ref);
|
res = JsonPointer.get(this.spec, ref);
|
||||||
|
@ -120,7 +124,7 @@ export class OpenAPIParser {
|
||||||
resetVisited() {
|
resetVisited() {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// check in dev mode
|
// check in dev mode
|
||||||
for (let k in this._refCounter._counter) {
|
for (const k in this._refCounter._counter) {
|
||||||
if (this._refCounter._counter[k] > 0) {
|
if (this._refCounter._counter[k] > 0) {
|
||||||
console.warn('Not exited reference: ' + k);
|
console.warn('Not exited reference: ' + k);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +134,9 @@ export class OpenAPIParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
exitRef<T>(ref: Referenced<T>) {
|
exitRef<T>(ref: Referenced<T>) {
|
||||||
if (!this.isRef(ref)) return;
|
if (!this.isRef(ref)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._refCounter.exit(ref.$ref);
|
this._refCounter.exit(ref.$ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +152,7 @@ export class OpenAPIParser {
|
||||||
this._refCounter.visit(obj.$ref);
|
this._refCounter.visit(obj.$ref);
|
||||||
if (visited && !forceCircular) {
|
if (visited && !forceCircular) {
|
||||||
// circular reference detected
|
// circular reference detected
|
||||||
|
// tslint:disable-next-line
|
||||||
return Object.assign({}, resolved, { 'x-circular-ref': true });
|
return Object.assign({}, resolved, { 'x-circular-ref': true });
|
||||||
}
|
}
|
||||||
// deref again in case one more $ref is here
|
// deref again in case one more $ref is here
|
||||||
|
@ -191,7 +198,7 @@ export class OpenAPIParser {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let { $ref: subSchemaRef, schema: subSchema } of allOfSchemas) {
|
for (const { $ref: subSchemaRef, schema: subSchema } of allOfSchemas) {
|
||||||
if (
|
if (
|
||||||
receiver.type !== subSchema.type &&
|
receiver.type !== subSchema.type &&
|
||||||
receiver.type !== undefined &&
|
receiver.type !== undefined &&
|
||||||
|
@ -244,7 +251,7 @@ export class OpenAPIParser {
|
||||||
findDerived($refs: string[]): Dict<string> {
|
findDerived($refs: string[]): Dict<string> {
|
||||||
const res: Dict<string> = {};
|
const res: Dict<string> = {};
|
||||||
const schemas = (this.spec.components && this.spec.components.schemas) || {};
|
const schemas = (this.spec.components && this.spec.components.schemas) || {};
|
||||||
for (let defName in schemas) {
|
for (const defName in schemas) {
|
||||||
const def = this.deref(schemas[defName]);
|
const def = this.deref(schemas[defName]);
|
||||||
if (
|
if (
|
||||||
def.allOf !== undefined &&
|
def.allOf !== undefined &&
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { ThemeInterface } from '../theme';
|
import defaultTheme, { ThemeInterface } from '../theme';
|
||||||
import { isNumeric, mergeObjects } from '../utils/helpers';
|
|
||||||
import { querySelector } from '../utils/dom';
|
import { querySelector } from '../utils/dom';
|
||||||
import defaultTheme from '../theme';
|
import { isNumeric, mergeObjects } from '../utils/helpers';
|
||||||
|
|
||||||
export interface RedocRawOptions {
|
export interface RedocRawOptions {
|
||||||
theme?: ThemeInterface;
|
theme?: ThemeInterface;
|
||||||
scrollYOffset?: number | string | Function;
|
scrollYOffset?: number | string | (() => number);
|
||||||
hideHostname?: boolean | string;
|
hideHostname?: boolean | string;
|
||||||
expandResponses?: string | 'all';
|
expandResponses?: string | 'all';
|
||||||
requiredPropsFirst?: boolean | string;
|
requiredPropsFirst?: boolean | string;
|
||||||
|
@ -17,34 +16,16 @@ export interface RedocRawOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
function argValueToBoolean(val?: string | boolean): boolean {
|
function argValueToBoolean(val?: string | boolean): boolean {
|
||||||
if (val === undefined) return false;
|
if (val === undefined) {
|
||||||
if (typeof val === 'string') return true;
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof val === 'string') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RedocNormalizedOptions {
|
export class RedocNormalizedOptions {
|
||||||
theme: ThemeInterface;
|
|
||||||
scrollYOffset: () => number;
|
|
||||||
hideHostname: boolean;
|
|
||||||
expandResponses: { [code: string]: boolean } | 'all';
|
|
||||||
requiredPropsFirst: boolean;
|
|
||||||
noAutoAuth: boolean;
|
|
||||||
nativeScrollbars: boolean;
|
|
||||||
pathInMiddlePanel: boolean;
|
|
||||||
untrustedSpec: boolean;
|
|
||||||
|
|
||||||
constructor(raw: RedocRawOptions) {
|
|
||||||
this.theme = mergeObjects({} as any, defaultTheme, raw.theme || {});
|
|
||||||
this.scrollYOffset = RedocNormalizedOptions.normalizeScrollYOffset(raw.scrollYOffset);
|
|
||||||
this.hideHostname = RedocNormalizedOptions.normalizeHideHostname(raw.hideHostname);
|
|
||||||
this.expandResponses = RedocNormalizedOptions.normalizeExpandResponses(raw.expandResponses);
|
|
||||||
this.requiredPropsFirst = argValueToBoolean(raw.requiredPropsFirst);
|
|
||||||
this.noAutoAuth = argValueToBoolean(raw.noAutoAuth);
|
|
||||||
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
|
|
||||||
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
|
|
||||||
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static normalizeExpandResponses(value: RedocRawOptions['expandResponses']) {
|
static normalizeExpandResponses(value: RedocRawOptions['expandResponses']) {
|
||||||
if (value === 'all') {
|
if (value === 'all') {
|
||||||
return 'all';
|
return 'all';
|
||||||
|
@ -98,4 +79,26 @@ export class RedocNormalizedOptions {
|
||||||
|
|
||||||
return () => 0;
|
return () => 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
theme: ThemeInterface;
|
||||||
|
scrollYOffset: () => number;
|
||||||
|
hideHostname: boolean;
|
||||||
|
expandResponses: { [code: string]: boolean } | 'all';
|
||||||
|
requiredPropsFirst: boolean;
|
||||||
|
noAutoAuth: boolean;
|
||||||
|
nativeScrollbars: boolean;
|
||||||
|
pathInMiddlePanel: boolean;
|
||||||
|
untrustedSpec: boolean;
|
||||||
|
|
||||||
|
constructor(raw: RedocRawOptions) {
|
||||||
|
this.theme = mergeObjects({} as any, defaultTheme, raw.theme || {});
|
||||||
|
this.scrollYOffset = RedocNormalizedOptions.normalizeScrollYOffset(raw.scrollYOffset);
|
||||||
|
this.hideHostname = RedocNormalizedOptions.normalizeHideHostname(raw.hideHostname);
|
||||||
|
this.expandResponses = RedocNormalizedOptions.normalizeExpandResponses(raw.expandResponses);
|
||||||
|
this.requiredPropsFirst = argValueToBoolean(raw.requiredPropsFirst);
|
||||||
|
this.noAutoAuth = argValueToBoolean(raw.noAutoAuth);
|
||||||
|
this.nativeScrollbars = argValueToBoolean(raw.nativeScrollbars);
|
||||||
|
this.pathInMiddlePanel = argValueToBoolean(raw.pathInMiddlePanel);
|
||||||
|
this.untrustedSpec = argValueToBoolean(raw.untrustedSpec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { debounce, bind } from 'decko';
|
import { bind, debounce } from 'decko';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
|
|
||||||
import { querySelector, isBrowser } from '../utils';
|
import { isBrowser, querySelector } from '../utils';
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
|
|
||||||
const EVENT = 'scroll';
|
const EVENT = 'scroll';
|
||||||
|
@ -18,11 +18,15 @@ export class ScrollService {
|
||||||
|
|
||||||
bind() {
|
bind() {
|
||||||
this._prevOffsetY = this.scrollY();
|
this._prevOffsetY = this.scrollY();
|
||||||
this._scrollParent && this._scrollParent.addEventListener('scroll', this.handleScroll);
|
if (this._scrollParent) {
|
||||||
|
this._scrollParent.addEventListener('scroll', this.handleScroll);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this._scrollParent && this._scrollParent.removeEventListener('scroll', this.handleScroll);
|
if (this._scrollParent) {
|
||||||
|
this._scrollParent.removeEventListener('scroll', this.handleScroll);
|
||||||
|
}
|
||||||
this._emiter.removeAllListeners(EVENT);
|
this._emiter.removeAllListeners(EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,12 +41,16 @@ export class ScrollService {
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementBellow(el: Element | null) {
|
isElementBellow(el: Element | null) {
|
||||||
if (el === null) return;
|
if (el === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return el.getBoundingClientRect().top > this.options.scrollYOffset();
|
return el.getBoundingClientRect().top > this.options.scrollYOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementAbove(el: Element | null) {
|
isElementAbove(el: Element | null) {
|
||||||
if (el === null) return;
|
if (el === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return Math.trunc(el.getBoundingClientRect().top) <= this.options.scrollYOffset();
|
return Math.trunc(el.getBoundingClientRect().top) <= this.options.scrollYOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +64,10 @@ export class ScrollService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
element.scrollIntoView();
|
element.scrollIntoView();
|
||||||
this._scrollParent &&
|
if (this._scrollParent && this._scrollParent.scrollBy) {
|
||||||
this._scrollParent.scrollBy &&
|
|
||||||
(this._scrollParent.scrollBy as any)(0, -this.options.scrollYOffset());
|
(this._scrollParent.scrollBy as any)(0, -this.options.scrollYOffset());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scrollIntoViewBySelector(selector: string) {
|
scrollIntoViewBySelector(selector: string) {
|
||||||
const element = querySelector(selector);
|
const element = querySelector(selector);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
import { computed, observable } from 'mobx';
|
||||||
import { OpenAPISpec } from '../types';
|
import { OpenAPISpec } from '../types';
|
||||||
import { observable, computed } from 'mobx';
|
|
||||||
|
|
||||||
// import { OpenAPIExternalDocumentation, OpenAPIInfo } from '../types';
|
// import { OpenAPIExternalDocumentation, OpenAPIInfo } from '../types';
|
||||||
|
|
||||||
import { MenuBuilder } from './MenuBuilder';
|
import { MenuBuilder } from './MenuBuilder';
|
||||||
import { OpenAPIParser } from './OpenAPIParser';
|
|
||||||
import { ApiInfoModel } from './models/ApiInfo';
|
import { ApiInfoModel } from './models/ApiInfo';
|
||||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
|
||||||
import { SecuritySchemesModel } from './models/SecuritySchemes';
|
import { SecuritySchemesModel } from './models/SecuritySchemes';
|
||||||
|
import { OpenAPIParser } from './OpenAPIParser';
|
||||||
|
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||||
/**
|
/**
|
||||||
* Store that containts all the specification related information in the form of tree
|
* Store that containts all the specification related information in the form of tree
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types';
|
import { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
|
||||||
import { isBrowser } from '../../utils/';
|
import { isBrowser } from '../../utils/';
|
||||||
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export class ApiInfoModel implements OpenAPIInfo {
|
export class ApiInfoModel implements OpenAPIInfo {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Referenced, OpenAPIExample } from '../../types';
|
import { OpenAPIExample, Referenced } from '../../types';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export class ExampleModel {
|
export class ExampleModel {
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import { observable, action } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
|
|
||||||
import { OpenAPIParameter, Referenced } from '../../types';
|
import { OpenAPIParameter, Referenced } from '../../types';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
|
||||||
import { SchemaModel } from './Schema';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
import { SchemaModel } from './Schema';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field or Parameter model ready to be used by components
|
* Field or Parameter model ready to be used by components
|
||||||
*/
|
*/
|
||||||
export class FieldModel {
|
export class FieldModel {
|
||||||
@observable public expanded: boolean = false;
|
@observable expanded: boolean = false;
|
||||||
|
|
||||||
public schema: SchemaModel;
|
schema: SchemaModel;
|
||||||
public name: string;
|
name: string;
|
||||||
public required: boolean;
|
required: boolean;
|
||||||
public description: string;
|
description: string;
|
||||||
public example?: string;
|
example?: string;
|
||||||
public deprecated: boolean;
|
deprecated: boolean;
|
||||||
public in?: string;
|
in?: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
parser: OpenAPIParser,
|
parser: OpenAPIParser,
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { observable, action } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
|
import slugify from 'slugify';
|
||||||
|
|
||||||
import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types';
|
import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types';
|
||||||
import { ContentItemModel } from '../MenuBuilder';
|
import { ContentItemModel } from '../MenuBuilder';
|
||||||
import { IMenuItem, MenuItemGroupType } from '../MenuStore';
|
import { IMenuItem, MenuItemGroupType } from '../MenuStore';
|
||||||
|
|
||||||
const slugify = require('slugify');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operations Group model ready to be used by components
|
* Operations Group model ready to be used by components
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +16,7 @@ export class GroupModel implements IMenuItem {
|
||||||
description?: string;
|
description?: string;
|
||||||
type: MenuItemGroupType;
|
type: MenuItemGroupType;
|
||||||
|
|
||||||
items: Array<ContentItemModel> = [];
|
items: ContentItemModel[] = [];
|
||||||
parent?: GroupModel;
|
parent?: GroupModel;
|
||||||
externalDocs?: OpenAPIExternalDocumentation;
|
externalDocs?: OpenAPIExternalDocumentation;
|
||||||
|
|
||||||
|
@ -48,7 +47,9 @@ export class GroupModel implements IMenuItem {
|
||||||
@action
|
@action
|
||||||
deactivate() {
|
deactivate() {
|
||||||
// disallow deactivating groups
|
// disallow deactivating groups
|
||||||
if (this.type === 'group') return;
|
if (this.type === 'group') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.active = false;
|
this.active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { observable, action, computed } from 'mobx';
|
import { action, computed, observable } from 'mobx';
|
||||||
|
|
||||||
import { OpenAPIMediaType } from '../../types';
|
import { OpenAPIMediaType } from '../../types';
|
||||||
import { MediaTypeModel } from './MediaType';
|
import { MediaTypeModel } from './MediaType';
|
||||||
|
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediaContent model ready to be sued by React components
|
* MediaContent model ready to be sued by React components
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import * as Sampler from 'openapi-sampler';
|
import * as Sampler from 'openapi-sampler';
|
||||||
|
|
||||||
import { OpenAPIExample, OpenAPIMediaType } from '../../types';
|
import { OpenAPIExample, OpenAPIMediaType } from '../../types';
|
||||||
import { SchemaModel } from './Schema';
|
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
import { SchemaModel } from './Schema';
|
||||||
|
|
||||||
import { mapValues, isJsonLike } from '../../utils';
|
import { isJsonLike, mapValues } from '../../utils';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { ExampleModel } from './Example';
|
import { ExampleModel } from './Example';
|
||||||
|
|
||||||
|
@ -39,14 +39,13 @@ export class MediaTypeModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) {
|
generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) {
|
||||||
const { schema, isRequestType } = this;
|
if (this.schema && this.schema.oneOf) {
|
||||||
if (schema && schema.oneOf) {
|
|
||||||
this.examples = {};
|
this.examples = {};
|
||||||
for (let subSchema of schema.oneOf) {
|
for (const subSchema of this.schema.oneOf) {
|
||||||
this.examples[subSchema.title] = {
|
this.examples[subSchema.title] = {
|
||||||
value: Sampler.sample(
|
value: Sampler.sample(
|
||||||
subSchema.rawSchema,
|
subSchema.rawSchema,
|
||||||
{ skipReadOnly: isRequestType, skipReadWrite: !isRequestType },
|
{ skipReadOnly: this.isRequestType, skipReadWrite: !this.isRequestType },
|
||||||
parser.spec,
|
parser.spec,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
@ -56,7 +55,7 @@ export class MediaTypeModel {
|
||||||
default: new ExampleModel(parser, {
|
default: new ExampleModel(parser, {
|
||||||
value: Sampler.sample(
|
value: Sampler.sample(
|
||||||
info.schema,
|
info.schema,
|
||||||
{ skipReadOnly: isRequestType, skipReadWrite: !isRequestType },
|
{ skipReadOnly: this.isRequestType, skipReadWrite: !this.isRequestType },
|
||||||
parser.spec,
|
parser.spec,
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import { observable, action } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
import { join as joinPaths } from 'path';
|
import { join as joinPaths } from 'path';
|
||||||
import { parse as urlParse } from 'url';
|
import { parse as urlParse } from 'url';
|
||||||
|
|
||||||
import { IMenuItem } from '../MenuStore';
|
import { IMenuItem } from '../MenuStore';
|
||||||
import { SecurityRequirementModel } from './SecurityRequirement';
|
|
||||||
import { GroupModel } from './Group.model';
|
import { GroupModel } from './Group.model';
|
||||||
|
import { SecurityRequirementModel } from './SecurityRequirement';
|
||||||
|
|
||||||
import { OpenAPIExternalDocumentation, OpenAPIServer } from '../../types';
|
import { OpenAPIExternalDocumentation, OpenAPIServer } from '../../types';
|
||||||
|
|
||||||
import { FieldModel } from './Field';
|
import { getOperationSummary, isAbsolutePath, JsonPointer, stripTrailingSlash } from '../../utils';
|
||||||
import { ResponseModel } from './Response';
|
|
||||||
import { RequestBodyModel } from './RequestBody';
|
|
||||||
import { CodeSample } from './types';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
|
||||||
import { ContentItemModel, ExtendedOpenAPIOperation } from '../MenuBuilder';
|
import { ContentItemModel, ExtendedOpenAPIOperation } from '../MenuBuilder';
|
||||||
import { JsonPointer, getOperationSummary, isAbsolutePath, stripTrailingSlash } from '../../utils';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
import { FieldModel } from './Field';
|
||||||
|
import { RequestBodyModel } from './RequestBody';
|
||||||
|
import { ResponseModel } from './Response';
|
||||||
|
import { CodeSample } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operation model ready to be used by components
|
* Operation model ready to be used by components
|
||||||
|
@ -30,7 +30,7 @@ export class OperationModel implements IMenuItem {
|
||||||
|
|
||||||
parent?: GroupModel;
|
parent?: GroupModel;
|
||||||
externalDocs?: OpenAPIExternalDocumentation;
|
externalDocs?: OpenAPIExternalDocumentation;
|
||||||
items: Array<ContentItemModel> = [];
|
items: ContentItemModel[] = [];
|
||||||
|
|
||||||
depth: number;
|
depth: number;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ export class OperationModel implements IMenuItem {
|
||||||
let hasSuccessResponses = false;
|
let hasSuccessResponses = false;
|
||||||
this.responses = Object.keys(operationSpec.responses || [])
|
this.responses = Object.keys(operationSpec.responses || [])
|
||||||
.filter(code => {
|
.filter(code => {
|
||||||
if (parseInt(code) >= 100 && parseInt(code) <= 399) {
|
if (parseInt(code, 10) >= 100 && parseInt(code, 10) <= 399) {
|
||||||
hasSuccessResponses = true;
|
hasSuccessResponses = true;
|
||||||
}
|
}
|
||||||
return isNumeric(code) || code === 'default';
|
return isNumeric(code) || code === 'default';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { OpenAPIRequestBody, Referenced } from '../../types';
|
import { OpenAPIRequestBody, Referenced } from '../../types';
|
||||||
|
|
||||||
import { MediaContentModel } from './MediaContent';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
import { MediaContentModel } from './MediaContent';
|
||||||
|
|
||||||
export class RequestBodyModel {
|
export class RequestBodyModel {
|
||||||
description: string;
|
description: string;
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import { observable, action } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
|
|
||||||
import { OpenAPIResponse, Referenced } from '../../types';
|
import { OpenAPIResponse, Referenced } from '../../types';
|
||||||
|
|
||||||
|
import { getStatusCodeType } from '../../utils';
|
||||||
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
import { FieldModel } from './Field';
|
import { FieldModel } from './Field';
|
||||||
import { MediaContentModel } from './MediaContent';
|
import { MediaContentModel } from './MediaContent';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
|
||||||
import { getStatusCodeType } from '../../utils';
|
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
|
||||||
|
|
||||||
export class ResponseModel {
|
export class ResponseModel {
|
||||||
@observable public expanded: boolean;
|
@observable expanded: boolean;
|
||||||
|
|
||||||
public content?: MediaContentModel;
|
content?: MediaContentModel;
|
||||||
public code: string;
|
code: string;
|
||||||
public description: string;
|
description: string;
|
||||||
public type: string;
|
type: string;
|
||||||
public headers: FieldModel[] = [];
|
headers: FieldModel[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
parser: OpenAPIParser,
|
parser: OpenAPIParser,
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { observable, action } from 'mobx';
|
import { action, observable } from 'mobx';
|
||||||
|
|
||||||
import { OpenAPISchema, Referenced } from '../../types';
|
import { OpenAPISchema, Referenced } from '../../types';
|
||||||
|
|
||||||
import { FieldModel } from './Field';
|
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||||
|
import { FieldModel } from './Field';
|
||||||
|
|
||||||
|
import { MergedOpenAPISchema } from '../';
|
||||||
import {
|
import {
|
||||||
detectType,
|
detectType,
|
||||||
humanizeConstraints,
|
humanizeConstraints,
|
||||||
|
@ -13,7 +14,6 @@ import {
|
||||||
isPrimitiveType,
|
isPrimitiveType,
|
||||||
JsonPointer,
|
JsonPointer,
|
||||||
} from '../../utils/';
|
} from '../../utils/';
|
||||||
import { MergedOpenAPISchema } from '../';
|
|
||||||
|
|
||||||
// TODO: refactor this model, maybe use getters instead of copying all the values
|
// TODO: refactor this model, maybe use getters instead of copying all the values
|
||||||
export class SchemaModel {
|
export class SchemaModel {
|
||||||
|
@ -69,9 +69,9 @@ export class SchemaModel {
|
||||||
|
|
||||||
parser.exitRef(schemaOrRef);
|
parser.exitRef(schemaOrRef);
|
||||||
|
|
||||||
for (let $ref of this.schema.parentRefs || []) {
|
for (const parent$ref of this.schema.parentRefs || []) {
|
||||||
// exit all the refs visited during allOf traverse
|
// exit all the refs visited during allOf traverse
|
||||||
parser.exitRef({ $ref });
|
parser.exitRef({ $ref: parent$ref });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,23 +174,25 @@ export class SchemaModel {
|
||||||
const derived = parser.findDerived([...(schema.namedParents || []), this._$ref]);
|
const derived = parser.findDerived([...(schema.namedParents || []), this._$ref]);
|
||||||
|
|
||||||
if (schema.oneOf) {
|
if (schema.oneOf) {
|
||||||
for (let variant of schema.oneOf) {
|
for (const variant of schema.oneOf) {
|
||||||
if (variant.$ref === undefined) continue;
|
if (variant.$ref === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const name = JsonPointer.dirName(variant.$ref);
|
const name = JsonPointer.dirName(variant.$ref);
|
||||||
derived[variant.$ref] = name;
|
derived[variant.$ref] = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapping = schema.discriminator!.mapping || {};
|
const mapping = schema.discriminator!.mapping || {};
|
||||||
for (let name in mapping) {
|
for (const name in mapping) {
|
||||||
derived[mapping[name]] = name;
|
derived[mapping[name]] = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const refs = Object.keys(derived);
|
const refs = Object.keys(derived);
|
||||||
this.oneOf = refs.map(ref => {
|
this.oneOf = refs.map(ref => {
|
||||||
const schema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true);
|
const innerSchema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true);
|
||||||
schema.title = derived[ref];
|
innerSchema.title = derived[ref];
|
||||||
return schema;
|
return innerSchema;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { OpenAPISecurityRequirement } from '../../types';
|
import { OpenAPISecurityRequirement } from '../../types';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
|
||||||
import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi';
|
import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi';
|
||||||
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export class SecurityRequirementModel {
|
export class SecurityRequirementModel {
|
||||||
schemes: {
|
schemes: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
sectionId: string;
|
sectionId: string;
|
||||||
type: string;
|
type: string;
|
||||||
scopes: string[];
|
scopes: string[];
|
||||||
}[];
|
}>;
|
||||||
|
|
||||||
constructor(requirement: OpenAPISecurityRequirement, parser: OpenAPIParser) {
|
constructor(requirement: OpenAPISecurityRequirement, parser: OpenAPIParser) {
|
||||||
const schemes = (parser.spec.components && parser.spec.components.securitySchemes) || {};
|
const schemes = (parser.spec.components && parser.spec.components.securitySchemes) || {};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { OpenAPISecurityScheme, Referenced } from '../../types';
|
import { OpenAPISecurityScheme, Referenced } from '../../types';
|
||||||
import { OpenAPIParser } from '../OpenAPIParser';
|
|
||||||
import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi';
|
import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi';
|
||||||
|
import { OpenAPIParser } from '../OpenAPIParser';
|
||||||
|
|
||||||
export class SecuritySchemeModel {
|
export class SecuritySchemeModel {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export type CodeSample = {
|
export interface CodeSample {
|
||||||
lang: string;
|
lang: string;
|
||||||
source: string;
|
source: string;
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import { render } from 'react-dom';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { render } from 'react-dom';
|
||||||
|
|
||||||
import { querySelector } from './utils/dom';
|
|
||||||
import { RedocStandalone } from './components/RedocStandalone';
|
import { RedocStandalone } from './components/RedocStandalone';
|
||||||
|
import { querySelector } from './utils/dom';
|
||||||
|
|
||||||
export const version = __REDOC_VERSION__;
|
export const version = __REDOC_VERSION__;
|
||||||
export const revision = __REDOC_REVISION__;
|
export const revision = __REDOC_REVISION__;
|
||||||
|
|
||||||
function attributesMap(element: Element) {
|
function attributesMap(element: Element) {
|
||||||
var res = {};
|
const res = {};
|
||||||
var elAttrs = element.attributes;
|
const elAttrs = element.attributes;
|
||||||
|
// tslint:disable-next-line
|
||||||
for (let i = 0; i < elAttrs.length; i++) {
|
for (let i = 0; i < elAttrs.length; i++) {
|
||||||
var attrib = elAttrs[i];
|
const attrib = elAttrs[i];
|
||||||
res[attrib.name] = attrib.value;
|
res[attrib.name] = attrib.value;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -20,7 +21,7 @@ function attributesMap(element: Element) {
|
||||||
function parseOptionsFromElement(element: Element) {
|
function parseOptionsFromElement(element: Element) {
|
||||||
const attrMap = attributesMap(element);
|
const attrMap = attributesMap(element);
|
||||||
const res = {};
|
const res = {};
|
||||||
for (let attrName in attrMap) {
|
for (const attrName in attrMap) {
|
||||||
const optionName = attrName.replace(/-(.)/g, (_, $1) => $1.toUpperCase());
|
const optionName = attrName.replace(/-(.)/g, (_, $1) => $1.toUpperCase());
|
||||||
res[optionName] = attrMap[attrName];
|
res[optionName] = attrMap[attrName];
|
||||||
// TODO: normalize options
|
// TODO: normalize options
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as styledComponents from 'styled-components';
|
import * as styledComponents from 'styled-components';
|
||||||
import { ThemedStyledComponentsModule } from 'styled-components';
|
|
||||||
|
|
||||||
import { ThemeInterface } from './theme';
|
import { ThemeInterface } from './theme';
|
||||||
|
|
||||||
|
@ -18,9 +17,9 @@ const {
|
||||||
keyframes,
|
keyframes,
|
||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
withTheme,
|
withTheme,
|
||||||
} = (styledComponents as ThemedStyledComponentsModule<any>) as ThemedStyledComponentsModule<
|
} = (styledComponents as styledComponents.ThemedStyledComponentsModule<
|
||||||
ThemeInterface
|
any
|
||||||
>;
|
>) as styledComponents.ThemedStyledComponentsModule<ThemeInterface>;
|
||||||
|
|
||||||
export { css, injectGlobal, keyframes, ThemeProvider, withTheme, withProps };
|
export { css, injectGlobal, keyframes, ThemeProvider, withTheme, withProps };
|
||||||
export default styled;
|
export default styled;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Omit } from './';
|
import { Omit } from './';
|
||||||
|
|
||||||
export type OpenAPISpec = {
|
export interface OpenAPISpec {
|
||||||
openapi: string;
|
openapi: string;
|
||||||
info: OpenAPIInfo;
|
info: OpenAPIInfo;
|
||||||
servers?: OpenAPIServer[];
|
servers?: OpenAPIServer[];
|
||||||
|
@ -9,7 +9,7 @@ export type OpenAPISpec = {
|
||||||
security?: OpenAPISecurityRequirement[];
|
security?: OpenAPISecurityRequirement[];
|
||||||
tags?: OpenAPITag[];
|
tags?: OpenAPITag[];
|
||||||
externalDocs?: OpenAPIExternalDocumentation;
|
externalDocs?: OpenAPIExternalDocumentation;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface OpenAPIInfo {
|
export interface OpenAPIInfo {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -21,29 +21,28 @@ export interface OpenAPIInfo {
|
||||||
license?: OpenAPILicense;
|
license?: OpenAPILicense;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OpenAPIServer = {
|
export interface OpenAPIServer {
|
||||||
url: string;
|
url: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
variables?: { [name: string]: OpenAPIServerVariable };
|
variables?: { [name: string]: OpenAPIServerVariable };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIServerVariable = {
|
export interface OpenAPIServerVariable {
|
||||||
enum?: string[];
|
enum?: string[];
|
||||||
default: string;
|
default: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIPaths = { [path: string]: OpenAPIPath };
|
export interface OpenAPIPaths {
|
||||||
export type OpenAPIRef = {
|
[path: string]: OpenAPIPath;
|
||||||
|
}
|
||||||
|
export interface OpenAPIRef {
|
||||||
$ref: string;
|
$ref: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type Referenced<T> = OpenAPIRef | T;
|
export type Referenced<T> = OpenAPIRef | T;
|
||||||
|
|
||||||
export type OpenAPIPath =
|
export interface OpenAPIPath {
|
||||||
// | OpenAPIRef // paths can't be external in redoc because they are prebundled
|
|
||||||
// | {
|
|
||||||
{
|
|
||||||
summary?: string;
|
summary?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
get?: OpenAPIOperation;
|
get?: OpenAPIOperation;
|
||||||
|
@ -55,25 +54,25 @@ export type OpenAPIPath =
|
||||||
patch?: OpenAPIOperation;
|
patch?: OpenAPIOperation;
|
||||||
trace?: OpenAPIOperation;
|
trace?: OpenAPIOperation;
|
||||||
servers?: OpenAPIServer[];
|
servers?: OpenAPIServer[];
|
||||||
parameters?: Referenced<OpenAPIParameter>[];
|
parameters?: Array<Referenced<OpenAPIParameter>>;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIOperation = {
|
export interface OpenAPIOperation {
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
summary?: string;
|
summary?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
externalDocs?: OpenAPIExternalDocumentation;
|
externalDocs?: OpenAPIExternalDocumentation;
|
||||||
operationId?: string;
|
operationId?: string;
|
||||||
parameters?: Referenced<OpenAPIParameter>[];
|
parameters?: Array<Referenced<OpenAPIParameter>>;
|
||||||
requestBody?: Referenced<OpenAPIRequestBody>;
|
requestBody?: Referenced<OpenAPIRequestBody>;
|
||||||
responses: OpenAPIResponses;
|
responses: OpenAPIResponses;
|
||||||
callbacks?: { [name: string]: Referenced<OpenAPICallback> };
|
callbacks?: { [name: string]: Referenced<OpenAPICallback> };
|
||||||
deprecated?: boolean;
|
deprecated?: boolean;
|
||||||
security?: OpenAPISecurityRequirement[];
|
security?: OpenAPISecurityRequirement[];
|
||||||
servers?: OpenAPIServer[];
|
servers?: OpenAPIServer[];
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIParameter = {
|
export interface OpenAPIParameter {
|
||||||
name: string;
|
name: string;
|
||||||
in?: OpenAPIParameterLocation;
|
in?: OpenAPIParameterLocation;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
@ -87,16 +86,16 @@ export type OpenAPIParameter = {
|
||||||
example?: any;
|
example?: any;
|
||||||
examples?: { [media: string]: Referenced<OpenAPIExample> };
|
examples?: { [media: string]: Referenced<OpenAPIExample> };
|
||||||
content?: { [media: string]: OpenAPIMediaType };
|
content?: { [media: string]: OpenAPIMediaType };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIExample = {
|
export interface OpenAPIExample {
|
||||||
value: any;
|
value: any;
|
||||||
summary?: string;
|
summary?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
externalValue?: string;
|
externalValue?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPISchema = {
|
export interface OpenAPISchema {
|
||||||
$ref?: string;
|
$ref?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
properties?: { [name: string]: OpenAPISchema };
|
properties?: { [name: string]: OpenAPISchema };
|
||||||
|
@ -133,27 +132,27 @@ export type OpenAPISchema = {
|
||||||
minProperties?: number;
|
minProperties?: number;
|
||||||
enum?: any[];
|
enum?: any[];
|
||||||
example?: any;
|
example?: any;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIDiscriminator = {
|
export interface OpenAPIDiscriminator {
|
||||||
propertyName: string;
|
propertyName: string;
|
||||||
mapping?: { [name: string]: string };
|
mapping?: { [name: string]: string };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIMediaType = {
|
export interface OpenAPIMediaType {
|
||||||
schema?: Referenced<OpenAPISchema>;
|
schema?: Referenced<OpenAPISchema>;
|
||||||
example?: any;
|
example?: any;
|
||||||
examples?: { [name: string]: Referenced<OpenAPIExample> };
|
examples?: { [name: string]: Referenced<OpenAPIExample> };
|
||||||
encoding?: { [field: string]: OpenAPIEncoding };
|
encoding?: { [field: string]: OpenAPIEncoding };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIEncoding = {
|
export interface OpenAPIEncoding {
|
||||||
contentType: string;
|
contentType: string;
|
||||||
headers?: { [name: string]: Referenced<OpenAPIHeader> };
|
headers?: { [name: string]: Referenced<OpenAPIHeader> };
|
||||||
style: OpenAPIParameterStyle;
|
style: OpenAPIParameterStyle;
|
||||||
explode: boolean;
|
explode: boolean;
|
||||||
allowReserved: boolean;
|
allowReserved: boolean;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIParameterLocation = 'query' | 'header' | 'path' | 'cookie';
|
export type OpenAPIParameterLocation = 'query' | 'header' | 'path' | 'cookie';
|
||||||
export type OpenAPIParameterStyle =
|
export type OpenAPIParameterStyle =
|
||||||
|
@ -165,30 +164,34 @@ export type OpenAPIParameterStyle =
|
||||||
| 'pipeDelimited'
|
| 'pipeDelimited'
|
||||||
| 'deepObject';
|
| 'deepObject';
|
||||||
|
|
||||||
export type OpenAPIRequestBody = {
|
export interface OpenAPIRequestBody {
|
||||||
description?: string;
|
description?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
content: { [mime: string]: OpenAPIMediaType };
|
content: { [mime: string]: OpenAPIMediaType };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIResponses = {
|
export interface OpenAPIResponses {
|
||||||
[code: string]: OpenAPIResponse;
|
[code: string]: OpenAPIResponse;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIResponse = {
|
export interface OpenAPIResponse {
|
||||||
description?: string;
|
description?: string;
|
||||||
headers?: { [name: string]: Referenced<OpenAPIHeader> };
|
headers?: { [name: string]: Referenced<OpenAPIHeader> };
|
||||||
content?: { [mime: string]: OpenAPIMediaType };
|
content?: { [mime: string]: OpenAPIMediaType };
|
||||||
links?: { [name: string]: Referenced<OpenAPILink> };
|
links?: { [name: string]: Referenced<OpenAPILink> };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPILink = {};
|
export interface OpenAPILink {
|
||||||
|
$ref?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type OpenAPIHeader = Omit<OpenAPIParameter, 'in' | 'name'>;
|
export type OpenAPIHeader = Omit<OpenAPIParameter, 'in' | 'name'>;
|
||||||
|
|
||||||
export type OpenAPICallback = {};
|
export interface OpenAPICallback {
|
||||||
|
$ref?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type OpenAPIComponents = {
|
export interface OpenAPIComponents {
|
||||||
schemas?: { [name: string]: Referenced<OpenAPISchema> };
|
schemas?: { [name: string]: Referenced<OpenAPISchema> };
|
||||||
responses?: { [name: string]: Referenced<OpenAPIResponse> };
|
responses?: { [name: string]: Referenced<OpenAPIResponse> };
|
||||||
parameters?: { [name: string]: Referenced<OpenAPIParameter> };
|
parameters?: { [name: string]: Referenced<OpenAPIParameter> };
|
||||||
|
@ -198,13 +201,13 @@ export type OpenAPIComponents = {
|
||||||
securitySchemes?: { [name: string]: Referenced<OpenAPISecurityScheme> };
|
securitySchemes?: { [name: string]: Referenced<OpenAPISecurityScheme> };
|
||||||
links?: { [name: string]: Referenced<OpenAPILink> };
|
links?: { [name: string]: Referenced<OpenAPILink> };
|
||||||
callbacks?: { [name: string]: Referenced<OpenAPICallback> };
|
callbacks?: { [name: string]: Referenced<OpenAPICallback> };
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPISecurityRequirement = {
|
export interface OpenAPISecurityRequirement {
|
||||||
[name: string]: string[];
|
[name: string]: string[];
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPISecurityScheme = {
|
export interface OpenAPISecurityScheme {
|
||||||
type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
|
type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
|
||||||
description?: string;
|
description?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
@ -234,27 +237,27 @@ export type OpenAPISecurityScheme = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
openIdConnectUrl?: string;
|
openIdConnectUrl?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPITag = {
|
export interface OpenAPITag {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
externalDocs?: OpenAPIExternalDocumentation;
|
externalDocs?: OpenAPIExternalDocumentation;
|
||||||
'x-displayName'?: string;
|
'x-displayName'?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIExternalDocumentation = {
|
export interface OpenAPIExternalDocumentation {
|
||||||
description?: string;
|
description?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPIContact = {
|
export interface OpenAPIContact {
|
||||||
name?: string;
|
name?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type OpenAPILicense = {
|
export interface OpenAPILicense {
|
||||||
name: string;
|
name: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
};
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export class JsonPointer {
|
||||||
* JsonPointerHelper.baseName('/path/foo/subpath', 2)
|
* JsonPointerHelper.baseName('/path/foo/subpath', 2)
|
||||||
*/
|
*/
|
||||||
static baseName(pointer, level = 1) {
|
static baseName(pointer, level = 1) {
|
||||||
let tokens = JsonPointer.parse(pointer);
|
const tokens = JsonPointer.parse(pointer);
|
||||||
return tokens[tokens.length - level];
|
return tokens[tokens.length - level];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export class JsonPointer {
|
||||||
* JsonPointerHelper.dirName('/path/foo/subpath', 2)
|
* JsonPointerHelper.dirName('/path/foo/subpath', 2)
|
||||||
*/
|
*/
|
||||||
static dirName(pointer, level = 1) {
|
static dirName(pointer, level = 1) {
|
||||||
let tokens = JsonPointer.parse(pointer);
|
const tokens = JsonPointer.parse(pointer);
|
||||||
return JsonPointerLib.compile(tokens.slice(0, tokens.length - level));
|
return JsonPointerLib.compile(tokens.slice(0, tokens.length - level));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +44,8 @@ export class JsonPointer {
|
||||||
* JsonPointerHelper.relative('/path', '/path/foo/subpath')
|
* JsonPointerHelper.relative('/path', '/path/foo/subpath')
|
||||||
*/
|
*/
|
||||||
static relative(from, to): string[] {
|
static relative(from, to): string[] {
|
||||||
let fromTokens = JsonPointer.parse(from);
|
const fromTokens = JsonPointer.parse(from);
|
||||||
let toTokens = JsonPointer.parse(to);
|
const toTokens = JsonPointer.parse(to);
|
||||||
return toTokens.slice(fromTokens.length);
|
return toTokens.slice(fromTokens.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,12 +70,12 @@ export class JsonPointer {
|
||||||
*/
|
*/
|
||||||
static join(base, tokens) {
|
static join(base, tokens) {
|
||||||
// TODO: optimize
|
// TODO: optimize
|
||||||
let baseTokens = JsonPointer.parse(base);
|
const baseTokens = JsonPointer.parse(base);
|
||||||
let resTokens = baseTokens.concat(tokens);
|
const resTokens = baseTokens.concat(tokens);
|
||||||
return JsonPointerLib.compile(resTokens);
|
return JsonPointerLib.compile(resTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get(object: Object, pointer: string) {
|
static get(object: object, pointer: string) {
|
||||||
return JsonPointerLib.get(object, pointer);
|
return JsonPointerLib.get(object, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@ export function querySelector(selector: string): Element | null {
|
||||||
export function html2Str(html: string): string {
|
export function html2Str(html: string): string {
|
||||||
return html
|
return html
|
||||||
.split(/<[^>]+>/)
|
.split(/<[^>]+>/)
|
||||||
.map(function(chunk) {
|
.map(chunk => {
|
||||||
return chunk.trim();
|
return chunk.trim();
|
||||||
})
|
})
|
||||||
.filter(function(trimmedChunk) {
|
.filter(trimmedChunk => {
|
||||||
return trimmedChunk.length > 0;
|
return trimmedChunk.length > 0;
|
||||||
})
|
})
|
||||||
.join(' ');
|
.join(' ');
|
||||||
|
|
|
@ -25,7 +25,7 @@ export function mapValues<T, P>(
|
||||||
iteratee: (val: T, key: string, obj: Dict<T>) => P,
|
iteratee: (val: T, key: string, obj: Dict<T>) => P,
|
||||||
): Dict<P> {
|
): Dict<P> {
|
||||||
const res: { [key: string]: P } = {};
|
const res: { [key: string]: P } = {};
|
||||||
for (let key in object) {
|
for (const key in object) {
|
||||||
if (object.hasOwnProperty(key)) {
|
if (object.hasOwnProperty(key)) {
|
||||||
res[key] = iteratee(object[key], key, object);
|
res[key] = iteratee(object[key], key, object);
|
||||||
}
|
}
|
||||||
|
@ -35,21 +35,23 @@ export function mapValues<T, P>(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* flattens collection using `prop` field as a children
|
* flattens collection using `prop` field as a children
|
||||||
* @param items collection items
|
* @param collectionItems collection items
|
||||||
* @param prop item property with child elements
|
* @param prop item property with child elements
|
||||||
*/
|
*/
|
||||||
export function flattenByProp<T extends object, P extends keyof T>(items: T[], prop: P): T[] {
|
export function flattenByProp<T extends object, P extends keyof T>(
|
||||||
|
collectionItems: T[],
|
||||||
|
prop: P,
|
||||||
|
): T[] {
|
||||||
const res: T[] = [];
|
const res: T[] = [];
|
||||||
const iterate = (items: T[]) => {
|
const iterate = (items: T[]) => {
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (const item of items) {
|
||||||
const item = items[i];
|
|
||||||
res.push(item);
|
res.push(item);
|
||||||
if (item[prop]) {
|
if (item[prop]) {
|
||||||
iterate(item[prop]);
|
iterate(item[prop]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
iterate(items);
|
iterate(collectionItems);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ export function isAbsolutePath(path: string): boolean {
|
||||||
return /^(?:[a-z]+:)?/i.test(path);
|
return /^(?:[a-z]+:)?/i.test(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isNumeric(n: any): n is Number {
|
export function isNumeric(n: any): n is number {
|
||||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
return !isNaN(parseFloat(n)) && isFinite(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ export const mergeObjects = <T extends object = object>(target: T, ...sources: T
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMergebleObject(target) && isMergebleObject(source)) {
|
if (isMergebleObject(target) && isMergebleObject(source)) {
|
||||||
Object.keys(source).forEach(function(key: string) {
|
Object.keys(source).forEach((key: string) => {
|
||||||
if (isMergebleObject(source[key])) {
|
if (isMergebleObject(source[key])) {
|
||||||
if (!target[key]) {
|
if (!target[key]) {
|
||||||
target[key] = {};
|
target[key] = {};
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import * as Prism from 'prismjs';
|
import * as Prism from 'prismjs';
|
||||||
import 'prismjs/components/prism-actionscript.js';
|
import 'prismjs/components/prism-actionscript.js';
|
||||||
|
import 'prismjs/components/prism-bash.js';
|
||||||
import 'prismjs/components/prism-c.js';
|
import 'prismjs/components/prism-c.js';
|
||||||
|
import 'prismjs/components/prism-coffeescript.js';
|
||||||
import 'prismjs/components/prism-cpp.js';
|
import 'prismjs/components/prism-cpp.js';
|
||||||
import 'prismjs/components/prism-csharp.js';
|
import 'prismjs/components/prism-csharp.js';
|
||||||
import 'prismjs/components/prism-php.js';
|
|
||||||
import 'prismjs/components/prism-coffeescript.js';
|
|
||||||
import 'prismjs/components/prism-go.js';
|
import 'prismjs/components/prism-go.js';
|
||||||
import 'prismjs/components/prism-haskell.js';
|
import 'prismjs/components/prism-haskell.js';
|
||||||
import 'prismjs/components/prism-java.js';
|
import 'prismjs/components/prism-java.js';
|
||||||
import 'prismjs/components/prism-lua.js';
|
import 'prismjs/components/prism-lua.js';
|
||||||
|
import 'prismjs/components/prism-markup.js'; // xml
|
||||||
import 'prismjs/components/prism-matlab.js';
|
import 'prismjs/components/prism-matlab.js';
|
||||||
|
import 'prismjs/components/prism-objectivec.js';
|
||||||
import 'prismjs/components/prism-perl.js';
|
import 'prismjs/components/prism-perl.js';
|
||||||
|
import 'prismjs/components/prism-php.js';
|
||||||
import 'prismjs/components/prism-python.js';
|
import 'prismjs/components/prism-python.js';
|
||||||
import 'prismjs/components/prism-r.js';
|
import 'prismjs/components/prism-r.js';
|
||||||
import 'prismjs/components/prism-ruby.js';
|
import 'prismjs/components/prism-ruby.js';
|
||||||
import 'prismjs/components/prism-bash.js';
|
|
||||||
import 'prismjs/components/prism-swift.js';
|
|
||||||
import 'prismjs/components/prism-objectivec.js';
|
|
||||||
import 'prismjs/components/prism-scala.js';
|
import 'prismjs/components/prism-scala.js';
|
||||||
import 'prismjs/components/prism-markup.js'; // xml
|
import 'prismjs/components/prism-swift.js';
|
||||||
|
|
||||||
import { injectGlobal } from '../styled-components';
|
import { injectGlobal } from '../styled-components';
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ const COLLAPSE_LEVEL = 2;
|
||||||
|
|
||||||
export function jsonToHTML(json) {
|
export function jsonToHTML(json) {
|
||||||
level = 1;
|
level = 1;
|
||||||
var output = '';
|
let output = '';
|
||||||
output += '<div class="redoc-json">';
|
output += '<div class="redoc-json">';
|
||||||
output += valueToHTML(json);
|
output += valueToHTML(json);
|
||||||
output += '</div>';
|
output += '</div>';
|
||||||
|
@ -11,7 +11,7 @@ export function jsonToHTML(json) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function htmlEncode(t) {
|
function htmlEncode(t) {
|
||||||
return t != undefined
|
return t !== undefined
|
||||||
? t
|
? t
|
||||||
.toString()
|
.toString()
|
||||||
.replace(/&/g, '&')
|
.replace(/&/g, '&')
|
||||||
|
@ -26,9 +26,9 @@ function decorateWithSpan(value, className) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function valueToHTML(value) {
|
function valueToHTML(value) {
|
||||||
var valueType = typeof value,
|
const valueType = typeof value;
|
||||||
output = '';
|
let output = '';
|
||||||
if (value == undefined) {
|
if (value === undefined || value === null) {
|
||||||
output += decorateWithSpan('null', 'type-null');
|
output += decorateWithSpan('null', 'type-null');
|
||||||
} else if (value && value.constructor === Array) {
|
} else if (value && value.constructor === Array) {
|
||||||
level++;
|
level++;
|
||||||
|
@ -63,12 +63,12 @@ function valueToHTML(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayToHTML(json) {
|
function arrayToHTML(json) {
|
||||||
var collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
||||||
var i, length;
|
let output =
|
||||||
var output =
|
|
||||||
'<div class="collapser"></div>[<span class="ellipsis"></span><ul class="array collapsible">';
|
'<div class="collapser"></div>[<span class="ellipsis"></span><ul class="array collapsible">';
|
||||||
var hasContents = false;
|
let hasContents = false;
|
||||||
for (i = 0, length = json.length; i < length; i++) {
|
const length = json.length;
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
hasContents = true;
|
hasContents = true;
|
||||||
output += '<li><div class="hoverable ' + collapsed + '">';
|
output += '<li><div class="hoverable ' + collapsed + '">';
|
||||||
output += valueToHTML(json[i]);
|
output += valueToHTML(json[i]);
|
||||||
|
@ -85,16 +85,14 @@ function arrayToHTML(json) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function objectToHTML(json) {
|
function objectToHTML(json) {
|
||||||
var collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
||||||
var i,
|
const keys = Object.keys(json);
|
||||||
key,
|
const length = keys.length;
|
||||||
length,
|
let output =
|
||||||
keys = Object.keys(json);
|
|
||||||
var output =
|
|
||||||
'<div class="collapser"></div>{<span class="ellipsis"></span><ul class="obj collapsible">';
|
'<div class="collapser"></div>{<span class="ellipsis"></span><ul class="obj collapsible">';
|
||||||
var hasContents = false;
|
let hasContents = false;
|
||||||
for (i = 0, length = keys.length; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
key = keys[i];
|
const key = keys[i];
|
||||||
hasContents = true;
|
hasContents = true;
|
||||||
output += '<li><div class="hoverable ' + collapsed + '">';
|
output += '<li><div class="hoverable ' + collapsed + '">';
|
||||||
output += '<span class="property">"' + htmlEncode(key) + '"</span>: ';
|
output += '<span class="property">"' + htmlEncode(key) + '"</span>: ';
|
||||||
|
|
|
@ -3,8 +3,8 @@ import { convertObj } from 'swagger2openapi';
|
||||||
import { OpenAPISpec } from '../types';
|
import { OpenAPISpec } from '../types';
|
||||||
|
|
||||||
export async function loadAndBundleSpec(specUrlOrObject: object | string): Promise<OpenAPISpec> {
|
export async function loadAndBundleSpec(specUrlOrObject: object | string): Promise<OpenAPISpec> {
|
||||||
const _parser = new JsonSchemaRefParser();
|
const parser = new JsonSchemaRefParser();
|
||||||
const spec = await _parser.bundle(specUrlOrObject, {
|
const spec = await parser.bundle(specUrlOrObject, {
|
||||||
resolve: { http: { withCredentials: false } },
|
resolve: { http: { withCredentials: false } },
|
||||||
} as object);
|
} as object);
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,8 @@ export function detectType(schema: OpenAPISchema): string {
|
||||||
return schema.type;
|
return schema.type;
|
||||||
}
|
}
|
||||||
const keywords = Object.keys(schemaKeywordTypes);
|
const keywords = Object.keys(schemaKeywordTypes);
|
||||||
for (var i = 0; i < keywords.length; i++) {
|
for (const keyword of keywords) {
|
||||||
let keyword = keywords[i];
|
const type = schemaKeywordTypes[keyword];
|
||||||
let type = schemaKeywordTypes[keyword];
|
|
||||||
if (schema[keyword] !== undefined) {
|
if (schema[keyword] !== undefined) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -127,9 +126,9 @@ export function humanizeConstraints(schema: OpenAPISchema): string[] {
|
||||||
} else {
|
} else {
|
||||||
stringRange = `[ ${schema.minLength} .. ${schema.maxLength} ] characters`;
|
stringRange = `[ ${schema.minLength} .. ${schema.maxLength} ] characters`;
|
||||||
}
|
}
|
||||||
} else if (schema.maxLength != undefined) {
|
} else if (schema.maxLength !== undefined) {
|
||||||
stringRange = `<= ${schema.maxLength} characters`;
|
stringRange = `<= ${schema.maxLength} characters`;
|
||||||
} else if (schema.minLength != undefined) {
|
} else if (schema.minLength !== undefined) {
|
||||||
if (schema.minLength === 1) {
|
if (schema.minLength === 1) {
|
||||||
stringRange = 'non-empty';
|
stringRange = 'non-empty';
|
||||||
} else {
|
} else {
|
||||||
|
@ -147,10 +146,10 @@ export function humanizeConstraints(schema: OpenAPISchema): string[] {
|
||||||
numberRange += ' .. ';
|
numberRange += ' .. ';
|
||||||
numberRange += schema.maximum;
|
numberRange += schema.maximum;
|
||||||
numberRange += schema.exclusiveMaximum ? ' )' : ' ]';
|
numberRange += schema.exclusiveMaximum ? ' )' : ' ]';
|
||||||
} else if (schema.maximum != undefined) {
|
} else if (schema.maximum !== undefined) {
|
||||||
numberRange = schema.exclusiveMaximum ? '< ' : '<= ';
|
numberRange = schema.exclusiveMaximum ? '< ' : '<= ';
|
||||||
numberRange += schema.maximum;
|
numberRange += schema.maximum;
|
||||||
} else if (schema.minimum != undefined) {
|
} else if (schema.minimum !== undefined) {
|
||||||
numberRange = schema.exclusiveMinimum ? '> ' : '>= ';
|
numberRange = schema.exclusiveMinimum ? '> ' : '>= ';
|
||||||
numberRange += schema.minimum;
|
numberRange += schema.minimum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
export function hexToRgb(hex: string): { r: number; g: number; b: number } {
|
export function hexToRgb(hex: string): { r: number; g: number; b: number } {
|
||||||
hex = hex.replace('#', '');
|
hex = hex.replace('#', '');
|
||||||
var r = parseInt(hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
|
const r = parseInt(hex.length === 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
|
||||||
var g = parseInt(hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
|
const g = parseInt(hex.length === 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
|
||||||
var b = parseInt(hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
|
const b = parseInt(hex.length === 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
|
||||||
return { r, g, b };
|
return { r, g, b };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
tslint.json
Normal file
26
tslint.json
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"extends": ["tslint:latest", "tslint-react"],
|
||||||
|
"rules": {
|
||||||
|
"interface-name": false,
|
||||||
|
"object-literal-sort-keys": false,
|
||||||
|
"jsx-no-multiline-js": false,
|
||||||
|
"jsx-wrap-multiline": false,
|
||||||
|
"max-classes-per-file": false,
|
||||||
|
"forin": false,
|
||||||
|
"prefer-conditional-expression": false,
|
||||||
|
"no-var-requires": false,
|
||||||
|
"no-object-literal-type-assertion": false,
|
||||||
|
"no-console": false,
|
||||||
|
"jsx-curly-spacing": false,
|
||||||
|
"max-line-length": false,
|
||||||
|
|
||||||
|
"quotemark": [true, "single", "avoid-template", "jsx-double"],
|
||||||
|
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
|
||||||
|
"arrow-parens": [true, "ban-single-arg-parens"],
|
||||||
|
"no-submodule-imports": [true, "prismjs", "perfect-scrollbar"],
|
||||||
|
"object-literal-key-quotes": [true, "as-needed"],
|
||||||
|
"no-unused-expression": [true, "allow-tagged-template"],
|
||||||
|
"semicolon": [true, "always", "ignore-bound-class-methods"],
|
||||||
|
"member-access": [true, "no-public"]
|
||||||
|
}
|
||||||
|
}
|
78
yarn.lock
78
yarn.lock
|
@ -1190,10 +1190,6 @@ colors@0.5.x:
|
||||||
version "0.5.1"
|
version "0.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
|
resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774"
|
||||||
|
|
||||||
colors@1.0.3:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
|
|
||||||
|
|
||||||
colors@^1.1.2, colors@~1.1.2:
|
colors@^1.1.2, colors@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
|
||||||
|
@ -1456,10 +1452,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
|
|
||||||
corser@~2.0.0:
|
|
||||||
version "2.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87"
|
|
||||||
|
|
||||||
cpx@^1.5.0:
|
cpx@^1.5.0:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/cpx/-/cpx-1.5.0.tgz#185be018511d87270dedccc293171e37655ab88f"
|
resolved "https://registry.yarnpkg.com/cpx/-/cpx-1.5.0.tgz#185be018511d87270dedccc293171e37655ab88f"
|
||||||
|
@ -1999,15 +1991,6 @@ ecc-jsbn@~0.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
jsbn "~0.1.0"
|
jsbn "~0.1.0"
|
||||||
|
|
||||||
ecstatic@^2.0.0:
|
|
||||||
version "2.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-2.2.1.tgz#b5087fad439dd9dd49d31e18131454817fe87769"
|
|
||||||
dependencies:
|
|
||||||
he "^1.1.1"
|
|
||||||
mime "^1.2.11"
|
|
||||||
minimist "^1.1.0"
|
|
||||||
url-join "^2.0.2"
|
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||||
|
@ -3107,7 +3090,7 @@ hawk@~6.0.2:
|
||||||
hoek "4.x.x"
|
hoek "4.x.x"
|
||||||
sntp "2.x.x"
|
sntp "2.x.x"
|
||||||
|
|
||||||
he@1.1.x, he@^1.1.1:
|
he@1.1.x:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||||
|
|
||||||
|
@ -3245,26 +3228,13 @@ http-proxy-middleware@~0.17.4:
|
||||||
lodash "^4.17.2"
|
lodash "^4.17.2"
|
||||||
micromatch "^2.3.11"
|
micromatch "^2.3.11"
|
||||||
|
|
||||||
http-proxy@^1.16.2, http-proxy@^1.8.1:
|
http-proxy@^1.16.2:
|
||||||
version "1.16.2"
|
version "1.16.2"
|
||||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742"
|
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742"
|
||||||
dependencies:
|
dependencies:
|
||||||
eventemitter3 "1.x.x"
|
eventemitter3 "1.x.x"
|
||||||
requires-port "1.x.x"
|
requires-port "1.x.x"
|
||||||
|
|
||||||
http-server@^0.10.0:
|
|
||||||
version "0.10.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/http-server/-/http-server-0.10.0.tgz#b2a446b16a9db87ed3c622ba9beb1b085b1234a7"
|
|
||||||
dependencies:
|
|
||||||
colors "1.0.3"
|
|
||||||
corser "~2.0.0"
|
|
||||||
ecstatic "^2.0.0"
|
|
||||||
http-proxy "^1.8.1"
|
|
||||||
opener "~1.4.0"
|
|
||||||
optimist "0.6.x"
|
|
||||||
portfinder "^1.0.13"
|
|
||||||
union "~0.4.3"
|
|
||||||
|
|
||||||
http-signature@~1.1.0:
|
http-signature@~1.1.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
|
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
|
||||||
|
@ -4503,7 +4473,7 @@ mime@1.4.1:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
|
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
|
||||||
|
|
||||||
mime@^1.2.11, mime@^1.3.4, mime@^1.5.0:
|
mime@^1.3.4, mime@^1.5.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||||
|
|
||||||
|
@ -4917,17 +4887,13 @@ openapi-sampler@1.0.0-beta.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
json-pointer "^0.6.0"
|
json-pointer "^0.6.0"
|
||||||
|
|
||||||
opener@~1.4.0:
|
|
||||||
version "1.4.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
|
|
||||||
|
|
||||||
opn@5.1.0, opn@^5.1.0:
|
opn@5.1.0, opn@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519"
|
resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519"
|
||||||
dependencies:
|
dependencies:
|
||||||
is-wsl "^1.1.0"
|
is-wsl "^1.1.0"
|
||||||
|
|
||||||
optimist@0.6.x, optimist@^0.6.1:
|
optimist@^0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
|
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5142,6 +5108,10 @@ perfect-scrollbar@^0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-0.7.1.tgz#0c256fb9c5cee401d60a299687a3f9a61487e0d5"
|
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-0.7.1.tgz#0c256fb9c5cee401d60a299687a3f9a61487e0d5"
|
||||||
|
|
||||||
|
perfect-scrollbar@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.3.0.tgz#61da56f94b58870d8e0a617bce649cee17d1e3b2"
|
||||||
|
|
||||||
performance-now@^0.2.0:
|
performance-now@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
|
||||||
|
@ -5178,7 +5148,7 @@ pluralize@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
|
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
|
||||||
|
|
||||||
portfinder@^1.0.13, portfinder@^1.0.9:
|
portfinder@^1.0.9:
|
||||||
version "1.0.13"
|
version "1.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
|
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5591,10 +5561,6 @@ qs@6.5.1, qs@~6.5.1:
|
||||||
version "6.5.1"
|
version "6.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
|
||||||
|
|
||||||
qs@~2.3.3:
|
|
||||||
version "2.3.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404"
|
|
||||||
|
|
||||||
qs@~6.4.0:
|
qs@~6.4.0:
|
||||||
version "6.4.0"
|
version "6.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
||||||
|
@ -6974,6 +6940,16 @@ tslib@^1.7.1, tslib@^1.8.0:
|
||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.8.1.tgz#6946af2d1d651a7b1863b531d6e5afa41aa44eac"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.8.1.tgz#6946af2d1d651a7b1863b531d6e5afa41aa44eac"
|
||||||
|
|
||||||
|
tslib@^1.8.1:
|
||||||
|
version "1.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
|
||||||
|
|
||||||
|
tslint-react@^3.4.0:
|
||||||
|
version "3.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.4.0.tgz#12ed3fc7063f3df988370206736b50acbce07e59"
|
||||||
|
dependencies:
|
||||||
|
tsutils "^2.13.1"
|
||||||
|
|
||||||
tslint@^5.7.0:
|
tslint@^5.7.0:
|
||||||
version "5.8.0"
|
version "5.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.8.0.tgz#1f49ad5b2e77c76c3af4ddcae552ae4e3612eb13"
|
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.8.0.tgz#1f49ad5b2e77c76c3af4ddcae552ae4e3612eb13"
|
||||||
|
@ -6996,6 +6972,12 @@ tsutils@^2.12.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib "^1.8.0"
|
tslib "^1.8.0"
|
||||||
|
|
||||||
|
tsutils@^2.13.1:
|
||||||
|
version "2.19.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7"
|
||||||
|
dependencies:
|
||||||
|
tslib "^1.8.1"
|
||||||
|
|
||||||
tty-browserify@0.0.0:
|
tty-browserify@0.0.0:
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
|
||||||
|
@ -7099,12 +7081,6 @@ union-value@^1.0.0:
|
||||||
is-extendable "^0.1.1"
|
is-extendable "^0.1.1"
|
||||||
set-value "^0.4.3"
|
set-value "^0.4.3"
|
||||||
|
|
||||||
union@~0.4.3:
|
|
||||||
version "0.4.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/union/-/union-0.4.6.tgz#198fbdaeba254e788b0efcb630bc11f24a2959e0"
|
|
||||||
dependencies:
|
|
||||||
qs "~2.3.3"
|
|
||||||
|
|
||||||
uniq@^1.0.1:
|
uniq@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
|
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
|
||||||
|
@ -7142,10 +7118,6 @@ urix@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||||
|
|
||||||
url-join@^2.0.2:
|
|
||||||
version "2.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.2.tgz#c072756967ad24b8b59e5741551caac78f50b8b7"
|
|
||||||
|
|
||||||
url-parse@1.0.x:
|
url-parse@1.0.x:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
|
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user