diff --git a/demo/playground/hmr-playground.tsx b/demo/playground/hmr-playground.tsx index b0d4c99e..9f55aa5f 100644 --- a/demo/playground/hmr-playground.tsx +++ b/demo/playground/hmr-playground.tsx @@ -5,8 +5,8 @@ import { AppContainer } from 'react-hot-loader'; import { Redoc, RedocProps } from '../../src/components/Redoc/Redoc'; import { AppStore } from '../../src/services/AppStore'; -import { loadAndBundleSpec } from '../../src/utils/loadAndBundleSpec'; import { RedocRawOptions } from '../../src/services/RedocNormalizedOptions'; +import { loadAndBundleSpec } from '../../src/utils/loadAndBundleSpec'; const renderRoot = (Component: typeof Redoc, props: RedocProps) => render( @@ -19,7 +19,7 @@ const renderRoot = (Component: typeof Redoc, props: RedocProps) => ); const big = window.location.search.indexOf('big') > -1; -const swagger = window.location.search.indexOf('swagger') > -1; //compatibility mode ? +const swagger = window.location.search.indexOf('swagger') > -1; // compatibility mode ? const specUrl = swagger ? 'swagger.yaml' : big ? 'big-openapi.json' : 'openapi.yaml'; @@ -29,7 +29,7 @@ const options: RedocRawOptions = {}; async function init() { const spec = await loadAndBundleSpec(specUrl); store = new AppStore(spec, specUrl, options); - renderRoot(Redoc, { store: store }); + renderRoot(Redoc, { store }); } init(); @@ -44,7 +44,7 @@ if (module.hot) { store = AppStore.fromJS(state); } - renderRoot(Redoc, { store: store }); + renderRoot(Redoc, { store }); }; module.hot.accept(['../../src/components/Redoc/Redoc'], reload()); diff --git a/package.json b/package.json index c864ee9c..43e90a80 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ "start": "webpack-dev-server --hot", "start:perf": "webpack-dev-server --env.prod --env.perf", "start:prod": "webpack-dev-server --env.prod", - "dev": "webpack-dashboard -- webpack-dev-server --hot", - "test": "npm run unit && npm run e2e", + "test": "npm run lint && npm run unit && npm run e2e", "unit": "jest", "e2e": "npm run e2e:clean && npm run e2e:tsc && cypress run", "e2e:tsc": "tsc -p tsconfig.e2e.json", @@ -20,8 +19,8 @@ "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", "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": "", "license": "MIT", @@ -51,7 +50,6 @@ "enzyme-adapter-react-16": "^1.0.4", "enzyme-to-json": "^3.2.2", "html-webpack-plugin": "^2.30.1", - "http-server": "^0.10.0", "jest": "^21.1.0", "mobx-react-devtools": "^4.2.15", "prettier": "^1.5.3", @@ -59,14 +57,14 @@ "puppeteer": "^0.10.2", "raf": "^3.4.0", "react-dev-utils": "^4.1.0", - "react-hot-loader": "3.0.0-beta.6", "rimraf": "^2.6.2", "source-map-loader": "^0.2.1", "style-loader": "^0.18.2", "ts-jest": "^21.0.1", "ts-node": "^3.3.0", "tslint": "^5.7.0", - "typescript": "^2.4.2", + "tslint-react": "^3.4.0", + "typescript": "^2.6.2", "webpack": "^3.10.0", "webpack-dev-server": "^2.9.5", "webpack-node-externals": "^1.6.0" @@ -84,9 +82,11 @@ "mobx": "^3.3.0", "mobx-react": "^4.3.3", "openapi-sampler": "1.0.0-beta.8", + "perfect-scrollbar": "^1.3.0", "prismjs": "^1.8.1", "prop-types": "^15.6.0", "react-dropdown": "^1.3.0", + "react-hot-loader": "3.0.0-beta.6", "react-perfect-scrollbar": "^0.2.2", "react-tabs": "^2.0.0", "remarkable": "^1.7.1", diff --git a/src/common-elements/dropdown.ts b/src/common-elements/dropdown.ts index 0ec99725..b122fd2c 100644 --- a/src/common-elements/dropdown.ts +++ b/src/common-elements/dropdown.ts @@ -1,15 +1,17 @@ import Dropdown from 'react-dropdown'; -import styled from '../styled-components'; -import { withProps } from '../styled-components'; +import styled, { 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[]; value: DropdownOption; onChange: (val: DropdownOption) => void; -}; +} export const StyledDropdown = withProps(styled(Dropdown))` min-width: 100px; diff --git a/src/common-elements/fields-layout.ts b/src/common-elements/fields-layout.ts index f59f1a22..7646da61 100644 --- a/src/common-elements/fields-layout.ts +++ b/src/common-elements/fields-layout.ts @@ -1,6 +1,6 @@ import styled from '../styled-components'; -import { deprecatedCss } from './mixins'; import { transparentizeHex } from '../utils/styled'; +import { deprecatedCss } from './mixins'; export const PropertiesTableCaption = styled.caption` text-align: right; diff --git a/src/common-elements/fields.ts b/src/common-elements/fields.ts index 207a6779..cbd639aa 100644 --- a/src/common-elements/fields.ts +++ b/src/common-elements/fields.ts @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import { PropertyNameCell } from './fields-layout'; import { transparentizeHex } from '../utils/styled'; +import { PropertyNameCell } from './fields-layout'; export const ClickablePropertyNameCell = PropertyNameCell.extend` cursor: pointer; diff --git a/src/common-elements/headers.ts b/src/common-elements/headers.ts index e80bac15..456fac0c 100644 --- a/src/common-elements/headers.ts +++ b/src/common-elements/headers.ts @@ -1,9 +1,9 @@ import styled, { css } from '../styled-components'; const headerFontSize = { - '1': '1.85714em', - '2': '1.57143em', - '3': '1.27em', + 1: '1.85714em', + 2: '1.57143em', + 3: '1.27em', }; export const headerCommonMixin = level => css` diff --git a/src/common-elements/linkify.ts b/src/common-elements/linkify.ts index 43287742..bf2590b6 100644 --- a/src/common-elements/linkify.ts +++ b/src/common-elements/linkify.ts @@ -1,5 +1,6 @@ import styled, { css } from 'styled-components'; +// tslint:disable-next-line export const linkifyMixin = className => css` ${className} { cursor: pointer; diff --git a/src/common-elements/mixins.ts b/src/common-elements/mixins.ts index 72a46801..d4129c89 100644 --- a/src/common-elements/mixins.ts +++ b/src/common-elements/mixins.ts @@ -6,7 +6,9 @@ export const deprecatedCss = css` `; export const hoverColor = color => { - if (!color) return ''; + if (!color) { + return ''; + } return css` &:hover { color: ${color}; diff --git a/src/common-elements/perfect-scrollbar.ts b/src/common-elements/perfect-scrollbar.ts index d35c376c..7a41d9fe 100644 --- a/src/common-elements/perfect-scrollbar.ts +++ b/src/common-elements/perfect-scrollbar.ts @@ -1,5 +1,5 @@ +import psStyles from 'perfect-scrollbar/css/perfect-scrollbar.css'; import styled, { injectGlobal } from '../styled-components'; -import psStyles from 'perfect-scrollbar/dist/css/perfect-scrollbar.css'; import PerfectScrollbarOriginal from 'react-perfect-scrollbar'; diff --git a/src/common-elements/schema.ts b/src/common-elements/schema.ts index 6ee18277..81ac2ecd 100644 --- a/src/common-elements/schema.ts +++ b/src/common-elements/schema.ts @@ -1,5 +1,4 @@ -import styled from '../styled-components'; -import { withProps } from '../styled-components'; +import styled, { withProps } from '../styled-components'; export const OneOfList = styled.ul` margin: 0; diff --git a/src/common-elements/shelfs.tsx b/src/common-elements/shelfs.tsx index 496b00db..9a5df8b4 100644 --- a/src/common-elements/shelfs.tsx +++ b/src/common-elements/shelfs.tsx @@ -8,7 +8,7 @@ const directionMap = { down: '0', }; -class _ShelfIcon extends React.PureComponent<{ +class IntShelfIcon extends React.PureComponent<{ className?: string; float?: 'left' | 'right'; 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'}; width: ${props => props.size || '18px'}; vertical-align: middle; diff --git a/src/common-elements/tabs.ts b/src/common-elements/tabs.ts index 38b7df83..1b54f59c 100644 --- a/src/common-elements/tabs.ts +++ b/src/common-elements/tabs.ts @@ -1,5 +1,5 @@ -import styled from '../styled-components'; import { Tabs as ReactTabs } from 'react-tabs'; +import styled from '../styled-components'; export { Tab, TabList, TabPanel } from 'react-tabs'; diff --git a/src/components/ApiInfo/ApiInfo.tsx b/src/components/ApiInfo/ApiInfo.tsx index a1768478..f1d51749 100644 --- a/src/components/ApiInfo/ApiInfo.tsx +++ b/src/components/ApiInfo/ApiInfo.tsx @@ -1,18 +1,18 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { AppStore } from '../../services/AppStore'; -import { SecurityDefs } from '../SecuritySchemes/SecuritySchemes'; +import { DarkRightPanel, MiddlePanel, Row } from '../../common-elements/'; import { Markdown } from '../Markdown/Markdown'; -import { MiddlePanel, DarkRightPanel, Row } from '../../common-elements/'; +import { SecurityDefs } from '../SecuritySchemes/SecuritySchemes'; import { ApiHeader, DownloadButton, InfoSpan, - InfoSpanBoxWrap, InfoSpanBox, + InfoSpanBoxWrap, } from './styled.elements'; interface ApiInfoProps { @@ -101,8 +101,8 @@ export class ApiInfo extends React.Component { components={{ 'security-definitions': { component: SecurityDefs, - propsSelector: store => ({ - securitySchemes: store!.spec.securitySchemes, + propsSelector: _store => ({ + securitySchemes: _store!.spec.securitySchemes, }), }, }} diff --git a/src/components/ApiInfo/styled.elements.ts b/src/components/ApiInfo/styled.elements.ts index f0798302..58df6b22 100644 --- a/src/components/ApiInfo/styled.elements.ts +++ b/src/components/ApiInfo/styled.elements.ts @@ -1,6 +1,6 @@ import styled from '../../styled-components'; -import { MiddlePanel, H1 } from '../../common-elements'; +import { H1, MiddlePanel } from '../../common-elements'; const delimiterWidth = 15; diff --git a/src/components/ApiLogo/ApiLogo.tsx b/src/components/ApiLogo/ApiLogo.tsx index 05acda2f..9fa01920 100644 --- a/src/components/ApiLogo/ApiLogo.tsx +++ b/src/components/ApiLogo/ApiLogo.tsx @@ -1,6 +1,6 @@ -import { OpenAPIInfo } from '../../types'; -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { OpenAPIInfo } from '../../types'; import { LogoImgEl, LogoWrap } from './styled.elements'; const LinkWrap = url => Component => {Component}; @@ -10,7 +10,9 @@ export class ApiLogo extends React.Component<{ info: OpenAPIInfo }> { render() { const { info } = this.props; const logoInfo = info['x-logo']; - if (!logoInfo || !logoInfo.url) return null; + if (!logoInfo || !logoInfo.url) { + return null; + } const logo = ( diff --git a/src/components/ContentItems/ContentItems.tsx b/src/components/ContentItems/ContentItems.tsx index f71e6b6f..56217c0e 100644 --- a/src/components/ContentItems/ContentItems.tsx +++ b/src/components/ContentItems/ContentItems.tsx @@ -1,13 +1,13 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { SECTION_ATTR } from '../../services/MenuStore'; import { Markdown } from '../Markdown/Markdown'; -import { DarkRightPanel, H1, MiddlePanel, ShareLink, Row } from '../../common-elements'; -import { Operation } from '../Operation/Operation'; +import { DarkRightPanel, H1, MiddlePanel, Row, ShareLink } from '../../common-elements'; import { ContentItemModel } from '../../services/MenuBuilder'; import { OperationModel } from '../../services/models'; +import { Operation } from '../Operation/Operation'; @observer export class ContentItems extends React.Component<{ @@ -15,14 +15,16 @@ export class ContentItems extends React.Component<{ }> { render() { const items = this.props.items; - if (items.length === 0) return null; + if (items.length === 0) { + return null; + } return items.map(item => ); } } -type ContentItemProps = { +interface ContentItemProps { item: ContentItemModel; -}; +} @observer export class ContentItem extends React.Component { diff --git a/src/components/DropdownOrLabel/DropdownOrLabel.tsx b/src/components/DropdownOrLabel/DropdownOrLabel.tsx index 91f039a0..220c56fe 100644 --- a/src/components/DropdownOrLabel/DropdownOrLabel.tsx +++ b/src/components/DropdownOrLabel/DropdownOrLabel.tsx @@ -1,6 +1,6 @@ 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 { Label?: React.ComponentClass; diff --git a/src/components/Endpoint/Endpoint.tsx b/src/components/Endpoint/Endpoint.tsx index f226a5a7..01d455e3 100644 --- a/src/components/Endpoint/Endpoint.tsx +++ b/src/components/Endpoint/Endpoint.tsx @@ -1,16 +1,16 @@ -import { ComponentWithOptions } from '../OptionsProvider'; import * as React from 'react'; -import { OperationModel } from '../../services'; import { ShelfIcon } from '../../common-elements'; +import { OperationModel } from '../../services'; +import { ComponentWithOptions } from '../OptionsProvider'; import { SelectOnClick } from '../SelectOnClick/SelectOnClick'; import { - OperationEndpointWrap, EndpointInfo, HttpVerb, + OperationEndpointWrap, + ServerItem, ServerRelativeURL, ServersOverlay, - ServerItem, ServerUrl, } from './styled.elements'; diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx index 4f0da684..d73c6f57 100644 --- a/src/components/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { Children } from 'react'; import styled from '../styled-components'; const ErrorWrapper = styled.div` @@ -14,7 +13,7 @@ export class ErrorBoundary extends React.Component<{}, { error?: Error }> { } componentDidCatch(error) { - this.setState({ error: error }); + this.setState({ error }); return false; } @@ -35,6 +34,6 @@ export class ErrorBoundary extends React.Component<{}, { error?: Error }> { ); } - return Children.only(this.props.children); + return React.Children.only(this.props.children); } } diff --git a/src/components/Fields/EnumValues.tsx b/src/components/Fields/EnumValues.tsx index 7b9634e2..0a38d565 100644 --- a/src/components/Fields/EnumValues.tsx +++ b/src/components/Fields/EnumValues.tsx @@ -9,7 +9,9 @@ export interface EnumValuesProps { export class EnumValues extends React.PureComponent { render() { const { values, type } = this.props; - if (!values.length) return null; + if (!values.length) { + return null; + } return (
diff --git a/src/components/Fields/Field.tsx b/src/components/Fields/Field.tsx index 90f80030..77cd4fed 100644 --- a/src/components/Fields/Field.tsx +++ b/src/components/Fields/Field.tsx @@ -1,5 +1,5 @@ -import { FieldDetails } from './FieldDetails'; import * as React from 'react'; +import { FieldDetails } from './FieldDetails'; import { ClickablePropertyNameCell, RequiredLabel } from '../../common-elements/fields'; diff --git a/src/components/Fields/FieldContstraints.tsx b/src/components/Fields/FieldContstraints.tsx index 64b3166e..c92e8f5c 100644 --- a/src/components/Fields/FieldContstraints.tsx +++ b/src/components/Fields/FieldContstraints.tsx @@ -7,7 +7,9 @@ export interface ConstraintsViewProps { export class ConstraintsView extends React.PureComponent { render() { - if (this.props.constraints.length === 0) return null; + if (this.props.constraints.length === 0) { + return null; + } return ( {' '} diff --git a/src/components/Fields/FieldDetail.tsx b/src/components/Fields/FieldDetail.tsx index 655871cc..2aa792fb 100644 --- a/src/components/Fields/FieldDetail.tsx +++ b/src/components/Fields/FieldDetail.tsx @@ -1,5 +1,5 @@ -import { ExampleValue, FieldLabel } from '../../common-elements/fields'; import * as React from 'react'; +import { ExampleValue, FieldLabel } from '../../common-elements/fields'; export interface FieldDetailProps { value?: any; @@ -8,7 +8,9 @@ export interface FieldDetailProps { export class FieldDetail extends React.PureComponent { render() { - if (this.props.value === undefined) return null; + if (this.props.value === undefined) { + return null; + } return (
{this.props.label} {' '} diff --git a/src/components/Fields/FieldDetails.tsx b/src/components/Fields/FieldDetails.tsx index 800fe6e4..e860772b 100644 --- a/src/components/Fields/FieldDetails.tsx +++ b/src/components/Fields/FieldDetails.tsx @@ -1,19 +1,19 @@ 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 { - RecursiveLabel, NullableLabel, PatternLabel, + RecursiveLabel, TypeFormat, TypeName, - TypeTitle, TypePrefix, + TypeTitle, } 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/'; diff --git a/src/components/JsonViewer/JsonViewer.tsx b/src/components/JsonViewer/JsonViewer.tsx index b1e9e973..7a2b42d4 100644 --- a/src/components/JsonViewer/JsonViewer.tsx +++ b/src/components/JsonViewer/JsonViewer.tsx @@ -23,8 +23,8 @@ class Json extends React.PureComponent { } clickListener = (event: MouseEvent) => { - var collapsed, - target = event.target as HTMLElement; + let collapsed; + const target = event.target as HTMLElement; if (target.className === 'collapser') { collapsed = target.parentElement!.getElementsByClassName('collapsible')[0]; if (collapsed.parentElement.classList.contains('collapsed')) { diff --git a/src/components/Markdown/Markdown.tsx b/src/components/Markdown/Markdown.tsx index a6dc31bb..c53454e5 100644 --- a/src/components/Markdown/Markdown.tsx +++ b/src/components/Markdown/Markdown.tsx @@ -1,17 +1,17 @@ import * as React from 'react'; import styled from '../../styled-components'; +import * as DOMPurify from 'dompurify'; import { AppStore, MarkdownRenderer } from '../../services'; import { ComponentWithOptions } from '../OptionsProvider'; -import * as DOMPurify from 'dompurify'; import { markdownCss } from './styles'; -export type MDComponent = { +export interface MDComponent { component: React.ComponentClass; propsSelector: (store?: AppStore) => any; attrs?: object; -}; +} export interface MarkdownProps { source: string; @@ -29,7 +29,7 @@ class InternalMarkdown extends ComponentWithOptions { super(props); 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 { throw new Error('When using components with Markdwon in ReDoc, store prop must be provided'); } - let sanitize: (string) => string; - - if (this.props.sanitize || this.options.untrustedSpec) { - sanitize = html => DOMPurify.sanitize(html); - } else { - sanitize = html => html; - } + const sanitize = + this.props.sanitize || this.options.untrustedSpec + ? (html: string) => DOMPurify.sanitize(html) + : (html: string) => html; const renderer = new MarkdownRenderer(); const parts = components ? renderer.renderMdWithComponents(source, components, raw) : [renderer.renderMd(source, raw)]; - if (!parts.length) return null; + if (!parts.length) { + return null; + } let appendClass = ' redoc-markdown'; - if (dense) appendClass += ' -dense'; - if (inline) appendClass += ' -inline'; + if (dense) { + appendClass += ' -dense'; + } + if (inline) { + appendClass += ' -inline'; + } if (inline) { return ( diff --git a/src/components/Markdown/styles.ts b/src/components/Markdown/styles.ts index d4a3d5e4..2622e3f8 100644 --- a/src/components/Markdown/styles.ts +++ b/src/components/Markdown/styles.ts @@ -1,5 +1,5 @@ -import { css } from '../../styled-components'; import { headerCommonMixin, linkifyMixin } from '../../common-elements'; +import { css } from '../../styled-components'; export const markdownCss = css` p { diff --git a/src/components/MediaTypeSwitch/MediaTypesSwitch.tsx b/src/components/MediaTypeSwitch/MediaTypesSwitch.tsx index 0d33062f..8c7a06b5 100644 --- a/src/components/MediaTypeSwitch/MediaTypesSwitch.tsx +++ b/src/components/MediaTypeSwitch/MediaTypesSwitch.tsx @@ -1,8 +1,8 @@ import { observer } from 'mobx-react'; import * as React from 'react'; -import { MediaContentModel, SchemaModel, MediaTypeModel } from '../../services/models'; import { DropdownProps } from '../../common-elements/dropdown'; +import { MediaContentModel, MediaTypeModel, SchemaModel } from '../../services/models'; export interface MediaTypeChildProps { schema: SchemaModel; @@ -18,15 +18,19 @@ export interface MediaTypesSwitchProps { @observer export class MediaTypesSwitch extends React.Component { switchMedia = ({ value }) => { - this.props.content && this.props.content.activate(parseInt(value)); + if (this.props.content) { + this.props.content.activate(parseInt(value, 10)); + } }; render() { 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; - let options = content.mediaTypes.map((mime, idx) => { + const options = content.mediaTypes.map((mime, idx) => { return { label: mime.name, value: idx.toString(), diff --git a/src/components/Operation/Operation.tsx b/src/components/Operation/Operation.tsx index 522a11a3..15493a23 100644 --- a/src/components/Operation/Operation.tsx +++ b/src/components/Operation/Operation.tsx @@ -8,13 +8,13 @@ import { Badge, DarkRightPanel, H2, MiddlePanel, Row } from '../../common-elemen 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 { 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'; diff --git a/src/components/OptionsProvider.ts b/src/components/OptionsProvider.ts index c86ce252..41b4e4ad 100644 --- a/src/components/OptionsProvider.ts +++ b/src/components/OptionsProvider.ts @@ -1,5 +1,5 @@ -import * as React from 'react'; import * as PropTypes from 'prop-types'; +import * as React from 'react'; import { RedocNormalizedOptions } from '../services/RedocNormalizedOptions'; diff --git a/src/components/Parameters/Parameters.tsx b/src/components/Parameters/Parameters.tsx index 305051cb..1c45ff56 100644 --- a/src/components/Parameters/Parameters.tsx +++ b/src/components/Parameters/Parameters.tsx @@ -1,17 +1,19 @@ +import * as React from 'react'; import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel'; import { ParametersGroup } from './ParametersGroup'; -import * as React from 'react'; import { UnderlinedHeader } from '../../common-elements'; -import { Schema } from '../Schema'; -import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch'; import { FieldModel, RequestBodyModel } from '../../services/models'; +import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch'; +import { Schema } from '../Schema'; import { MediaContentModel } from '../../services'; function safePush(obj, prop, item) { - if (!obj[prop]) obj[prop] = []; + if (!obj[prop]) { + obj[prop] = []; + } obj[prop].push(item); } @@ -24,7 +26,7 @@ const PARAM_PLACES = ['path', 'query', 'cookie', 'header']; export class Parameters extends React.PureComponent { orderParams(params: FieldModel[]): Dict { - let res = {}; + const res = {}; params.forEach(param => { safePush(res, param.in, param); }); @@ -37,7 +39,7 @@ export class Parameters extends React.PureComponent { return null; } - let paramsMap = this.orderParams(parameters); + const paramsMap = this.orderParams(parameters); const paramsPlaces = parameters.length > 0 ? PARAM_PLACES : []; @@ -54,17 +56,18 @@ export class Parameters extends React.PureComponent { } } +function DropdownWithinHeader(props) { + return ( + + Request Body schema: + + ); +} + function BodyContent(props: { content: MediaContentModel }): JSX.Element { const { content } = props; return ( - ( - - Request Body schema: - - )} - > + {({ schema }) => { return ; }} diff --git a/src/components/Parameters/ParametersGroup.tsx b/src/components/Parameters/ParametersGroup.tsx index 31d7c633..99cf32c1 100644 --- a/src/components/Parameters/ParametersGroup.tsx +++ b/src/components/Parameters/ParametersGroup.tsx @@ -16,7 +16,9 @@ export interface ParametersGroupProps { export class ParametersGroup extends React.PureComponent { render() { const { place, parameters } = this.props; - if (!parameters || !parameters.length) return null; + if (!parameters || !parameters.length) { + return null; + } return (
diff --git a/src/components/PayloadSamples/MediaTypeSamples.tsx b/src/components/PayloadSamples/MediaTypeSamples.tsx index cfb46b1b..682c8ae7 100644 --- a/src/components/PayloadSamples/MediaTypeSamples.tsx +++ b/src/components/PayloadSamples/MediaTypeSamples.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; +import { SmallTabs, Tab, TabList, TabPanel } from '../../common-elements'; import { MediaTypeModel } from '../../services/models'; import { StyledJson } from '../JsonViewer/JsonViewer'; import { SourceCode } from '../SourceCode/SourceCode'; -import { SmallTabs, TabList, TabPanel, Tab } from '../../common-elements'; import { NoSampleLabel } from './styled.elements'; import { isJsonLike, langFromMime } from '../../utils'; @@ -24,7 +24,9 @@ export class MediaTypeSamples extends React.Component { (sample && ) || { noSample }; const examplesNames = Object.keys(examples); - if (examplesNames.length === 0) return noSample; + if (examplesNames.length === 0) { + return noSample; + } if (examplesNames.length > 1) { return ( diff --git a/src/components/PayloadSamples/PayloadSamples.tsx b/src/components/PayloadSamples/PayloadSamples.tsx index 50f6670c..03db3a70 100644 --- a/src/components/PayloadSamples/PayloadSamples.tsx +++ b/src/components/PayloadSamples/PayloadSamples.tsx @@ -1,6 +1,6 @@ -import { MediaTypeSamples } from './MediaTypeSamples'; -import * as React from 'react' import { observer } from 'mobx-react'; +import * as React from 'react'; +import { MediaTypeSamples } from './MediaTypeSamples'; import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch'; @@ -16,15 +16,18 @@ export interface PayloadSamplesProps { export class PayloadSamples extends React.Component { render() { const mimeContent = this.props.content; - if (mimeContent === undefined) return null; + if (mimeContent === undefined) { + return null; + } return ( - } - > + {mediaType => } ); } + + private renderDropdown = props => { + return ; + }; } diff --git a/src/components/PayloadSamples/styled.elements.ts b/src/components/PayloadSamples/styled.elements.ts index 6e2f8abf..aa7f3e43 100644 --- a/src/components/PayloadSamples/styled.elements.ts +++ b/src/components/PayloadSamples/styled.elements.ts @@ -27,7 +27,6 @@ export const InvertedSimpleDropdown = styled(SimpleDropdown)` } `; - export const NoSampleLabel = styled.div` font-family: ${props => props.theme.code.fontFamily}; font-size: 12px; diff --git a/src/components/Redoc/Redoc.tsx b/src/components/Redoc/Redoc.tsx index 3faeaf9a..95220a15 100644 --- a/src/components/Redoc/Redoc.tsx +++ b/src/components/Redoc/Redoc.tsx @@ -1,16 +1,16 @@ -import * as React from 'react'; import * as PropTypes from 'prop-types'; +import * as React from 'react'; 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 { ApiInfo } from '../ApiInfo/ApiInfo'; +import { ApiLogo } from '../ApiLogo/ApiLogo'; +import { ContentItems } from '../ContentItems/ContentItems'; import { OptionsProvider } from '../OptionsProvider'; +import { SideMenu } from '../SideMenu/SideMenu'; import { StickySidebar } from '../StickySidebar/StickySidebar'; +import { ApiContent, RedocWrap } from './elements'; export interface RedocProps { store: AppStore; diff --git a/src/components/RedocStandalone.tsx b/src/components/RedocStandalone.tsx index 89cd26cf..af8c521e 100644 --- a/src/components/RedocStandalone.tsx +++ b/src/components/RedocStandalone.tsx @@ -1,11 +1,11 @@ -import * as React from 'react'; 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 { ErrorBoundary } from './ErrorBoundary'; +import { Loading } from './Loading/Loading'; +import { Redoc } from './Redoc/Redoc'; +import { StoreProvider } from './StoreProvider'; export interface RedocStandaloneProps { spec?: object; diff --git a/src/components/RequestSamples/RequestSamples.tsx b/src/components/RequestSamples/RequestSamples.tsx index 4dbd596e..5f913ff7 100644 --- a/src/components/RequestSamples/RequestSamples.tsx +++ b/src/components/RequestSamples/RequestSamples.tsx @@ -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 * as React from 'react'; 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 { operation: OperationModel; diff --git a/src/components/ResponseSamples/ResponseSamples.tsx b/src/components/ResponseSamples/ResponseSamples.tsx index 51d1d623..590b4769 100644 --- a/src/components/ResponseSamples/ResponseSamples.tsx +++ b/src/components/ResponseSamples/ResponseSamples.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; 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'; export interface ResponseSampleProps { diff --git a/src/components/Responses/Response.tsx b/src/components/Responses/Response.tsx index 77879746..6f521f4b 100644 --- a/src/components/Responses/Response.tsx +++ b/src/components/Responses/Response.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { ResponseModel } from '../../services/models'; import { UnderlinedHeader } from '../../common-elements'; -import { Schema } from '../Schema'; -import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch'; import { DropdownOrLabel } from '../DropdownOrLabel/DropdownOrLabel'; +import { MediaTypesSwitch } from '../MediaTypeSwitch/MediaTypesSwitch'; +import { Schema } from '../Schema'; import { ResponseHeaders } from './ResponseHeaders'; import { ResponseDetailsWrap, StyledResponseTitle } from './styled.elements'; @@ -38,14 +38,7 @@ export class ResponseView extends React.Component<{ response: ResponseModel }> { !empty && ( - ( - - Response Schema: - - )} - > + {({ schema }) => { return ; }} @@ -55,4 +48,12 @@ export class ResponseView extends React.Component<{ response: ResponseModel }> {
); } + + private renderDropdown = props => { + return ( + + Response Schema: + + ); + }; } diff --git a/src/components/Responses/ResponseHeaders.tsx b/src/components/Responses/ResponseHeaders.tsx index 275c4659..756ae8a3 100644 --- a/src/components/Responses/ResponseHeaders.tsx +++ b/src/components/Responses/ResponseHeaders.tsx @@ -1,10 +1,10 @@ -import { PropertiesTable } from '../../common-elements/fields-layout'; 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 { mapWithLast } from '../../utils'; import { Field } from '../Fields/Field'; +import { HeadersCaption } from './styled.elements'; export interface ResponseHeadersProps { headers?: FieldModel[]; diff --git a/src/components/Responses/ResponseTitle.tsx b/src/components/Responses/ResponseTitle.tsx index ef1625fa..00169340 100644 --- a/src/components/Responses/ResponseTitle.tsx +++ b/src/components/Responses/ResponseTitle.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import { Markdown } from '../Markdown/Markdown'; import { ShelfIcon } from '../../common-elements'; +import { Markdown } from '../Markdown/Markdown'; export interface ResponseTitleProps { code: string; diff --git a/src/components/Responses/ResponsesList.tsx b/src/components/Responses/ResponsesList.tsx index c12f29c5..f66518b9 100644 --- a/src/components/Responses/ResponsesList.tsx +++ b/src/components/Responses/ResponsesList.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import styled from 'styled-components'; -import { ResponseView } from './Response'; import { ResponseModel } from '../../services/models'; +import { ResponseView } from './Response'; const ResponsesHeader = styled.h3` font-size: 18px; @@ -19,7 +19,9 @@ export class ResponsesList extends React.PureComponent { render() { const { responses } = this.props; - if (!responses || responses.length === 0) return null; + if (!responses || responses.length === 0) { + return null; + } return (
diff --git a/src/components/Responses/styled.elements.ts b/src/components/Responses/styled.elements.ts index 632c2e77..7f4c7eab 100644 --- a/src/components/Responses/styled.elements.ts +++ b/src/components/Responses/styled.elements.ts @@ -1,8 +1,8 @@ import styled from '../../styled-components'; -import { ResponseTitle } from './ResponseTitle'; import { UnderlinedHeader } from '../../common-elements'; import { transparentizeHex } from '../../utils'; +import { ResponseTitle } from './ResponseTitle'; export const StyledResponseTitle = styled(ResponseTitle)` padding: 10px; diff --git a/src/components/Schema/ArraySchema.tsx b/src/components/Schema/ArraySchema.tsx index 8d4fa594..5307b112 100644 --- a/src/components/Schema/ArraySchema.tsx +++ b/src/components/Schema/ArraySchema.tsx @@ -1,8 +1,8 @@ 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 { render() { diff --git a/src/components/Schema/DiscriminatorDropdown.tsx b/src/components/Schema/DiscriminatorDropdown.tsx index adc629b0..5301de89 100644 --- a/src/components/Schema/DiscriminatorDropdown.tsx +++ b/src/components/Schema/DiscriminatorDropdown.tsx @@ -1,7 +1,7 @@ -import * as React from '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'; @observer @@ -10,7 +10,9 @@ export class DiscriminatorDropdown extends React.Component<{ enumValues: string[]; }> { sortOptions(options: DropdownOption[], enumValues: string[]): void { - if (enumValues.length === 0) return; + if (enumValues.length === 0) { + return; + } const enumOrder = {}; @@ -48,7 +50,7 @@ export class DiscriminatorDropdown extends React.Component<{ } changeActiveChild = ({ value }) => { - const idx = parseInt(value); + const idx = parseInt(value, 10); this.props.parent.activateOneOf(idx); }; } diff --git a/src/components/Schema/ObjectSchema.tsx b/src/components/Schema/ObjectSchema.tsx index 9767bdc8..1f0dde68 100644 --- a/src/components/Schema/ObjectSchema.tsx +++ b/src/components/Schema/ObjectSchema.tsx @@ -1,17 +1,17 @@ -import * as React from '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 { InnerPropertiesWrap, PropertiesTable, PropertiesTableCaption, PropertyCellWithInner, } from '../../common-elements/fields-layout'; +import { Field } from '../Fields/Field'; +import { DiscriminatorDropdown } from './DiscriminatorDropdown'; +import { Schema, SchemaProps } from './Schema'; import { mapWithLast } from '../../utils'; diff --git a/src/components/Schema/OneOfSchema.tsx b/src/components/Schema/OneOfSchema.tsx index 25068985..01b3825c 100644 --- a/src/components/Schema/OneOfSchema.tsx +++ b/src/components/Schema/OneOfSchema.tsx @@ -1,8 +1,33 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; -import { OneOfButton, OneOfLabel, OneOfList } from '../../common-elements/schema'; -import { SchemaProps, Schema } from './Schema'; +import { + 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 { + render() { + const { idx, schema, subSchema } = this.props; + return ( + + {subSchema.title || subSchema.displayType} + + ); + } + + activateOneOf() { + this.props.schema.activateOneOf(this.props.idx); + } +} @observer export class OneOfSchema extends React.Component { @@ -17,13 +42,7 @@ export class OneOfSchema extends React.Component { {schema.oneOfType} {oneOf.map((subSchema, idx) => ( - schema.activateOneOf(idx)} - > - {subSchema.title || subSchema.displayType} - + ))} diff --git a/src/components/Schema/Schema.tsx b/src/components/Schema/Schema.tsx index 2b712822..012164b0 100644 --- a/src/components/Schema/Schema.tsx +++ b/src/components/Schema/Schema.tsx @@ -1,14 +1,14 @@ -import * as React from '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 { FieldDetails } from '../Fields/FieldDetails'; import { SchemaModel } from '../../services/models'; +import { ArraySchema } from './ArraySchema'; import { ObjectSchema } from './ObjectSchema'; import { OneOfSchema } from './OneOfSchema'; -import { ArraySchema } from './ArraySchema'; export interface SchemaProps { schema: SchemaModel; @@ -21,7 +21,9 @@ export interface SchemaProps { export class Schema extends React.Component> { render() { const { schema } = this.props; - if (!schema) return Schema not provided ; + if (!schema) { + return Schema not provided ; + } const { type, oneOf, discriminatorProp, isCircular } = schema; if (isCircular) { diff --git a/src/components/SecurityRequirement/SecuirityRequirement.tsx b/src/components/SecurityRequirement/SecuirityRequirement.tsx index 28603773..1ca5f003 100644 --- a/src/components/SecurityRequirement/SecuirityRequirement.tsx +++ b/src/components/SecurityRequirement/SecuirityRequirement.tsx @@ -2,8 +2,8 @@ import * as React from 'react'; import styled from '../../styled-components'; import { transparentizeHex } from '../../utils/styled'; -import { SecurityRequirementModel } from '../../services/models/SecurityRequirement'; import { UnderlinedHeader } from '../../common-elements/headers'; +import { SecurityRequirementModel } from '../../services/models/SecurityRequirement'; const ScopeName = styled.code` font-size: ${props => props.theme.code.fontSize}; @@ -57,7 +57,9 @@ export interface SecurityRequirementsProps { export class SecurityRequirements extends React.PureComponent { render() { const securities = this.props.securities; - if (!securities.length) return null; + if (!securities.length) { + return null; + } return (
diff --git a/src/components/SecuritySchemes/SecuritySchemes.tsx b/src/components/SecuritySchemes/SecuritySchemes.tsx index 0282a8c3..3cecdff5 100644 --- a/src/components/SecuritySchemes/SecuritySchemes.tsx +++ b/src/components/SecuritySchemes/SecuritySchemes.tsx @@ -2,10 +2,10 @@ import * as React from 'react'; import { SecuritySchemesModel } from '../../services/models'; -import styled from '../../styled-components'; import { H2, ShareLink } from '../../common-elements'; -import { Markdown } from '../Markdown/Markdown'; +import styled from '../../styled-components'; import { OpenAPISecurityScheme } from '../../types'; +import { Markdown } from '../Markdown/Markdown'; const AUTH_TYPES = { oauth2: 'OAuth2', @@ -76,7 +76,9 @@ export interface SecurityDefsProps { export class SecurityDefs extends React.PureComponent { render() { - if (!this.props.securitySchemes) return null; + if (!this.props.securitySchemes) { + return null; + } return (
diff --git a/src/components/SelectOnClick/SelectOnClick.tsx b/src/components/SelectOnClick/SelectOnClick.tsx index 87ba359a..d8e3d503 100644 --- a/src/components/SelectOnClick/SelectOnClick.tsx +++ b/src/components/SelectOnClick/SelectOnClick.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { ClipboardService } from '../../services'; export class SelectOnClick extends React.PureComponent { + private child: HTMLDivElement | null; handleClick = () => { ClipboardService.selectElement(this.refs.child); }; @@ -10,7 +11,7 @@ export class SelectOnClick extends React.PureComponent { render() { const { children } = this.props; return ( -
+
(this.child = el)} onClick={this.handleClick}> {children}
); diff --git a/src/components/SideMenu/MenuItem.tsx b/src/components/SideMenu/MenuItem.tsx index 489b9e37..565ee65a 100644 --- a/src/components/SideMenu/MenuItem.tsx +++ b/src/components/SideMenu/MenuItem.tsx @@ -1,10 +1,10 @@ -import * as React from '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 { IMenuItem, OperationModel } from '../../services'; import { MenuItems } from './MenuItems'; +import { MenuItemLabel, MenuItemLi, MenuItemTitle, OperationBadge } from './styled.elements'; interface MenuItemProps { item: IMenuItem; @@ -42,9 +42,9 @@ export class MenuItem extends React.Component { } } -export type OperationMenuItemContentProps = { +export interface OperationMenuItemContentProps { item: OperationModel; -}; +} @observer class OperationMenuItemContent extends React.Component { diff --git a/src/components/SideMenu/MenuItems.tsx b/src/components/SideMenu/MenuItems.tsx index dca21d3e..9a004b60 100644 --- a/src/components/SideMenu/MenuItems.tsx +++ b/src/components/SideMenu/MenuItems.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { IMenuItem } from '../../services'; -import { MenuItemUl } from './styled.elements'; import { MenuItem } from './MenuItem'; +import { MenuItemUl } from './styled.elements'; interface MenuItemsProps { items: IMenuItem[]; diff --git a/src/components/SideMenu/SideMenu.tsx b/src/components/SideMenu/SideMenu.tsx index 67e3c5c9..bb0a106a 100644 --- a/src/components/SideMenu/SideMenu.tsx +++ b/src/components/SideMenu/SideMenu.tsx @@ -1,8 +1,8 @@ -import { ComponentWithOptions } from '../OptionsProvider'; -import * as React from '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 { PerfectScrollbar } from '../../common-elements/perfect-scrollbar'; diff --git a/src/components/SideMenu/styled.elements.ts b/src/components/SideMenu/styled.elements.ts index 90ccdf5d..1db72807 100644 --- a/src/components/SideMenu/styled.elements.ts +++ b/src/components/SideMenu/styled.elements.ts @@ -1,5 +1,5 @@ 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({ className: props => `operation-type ${props.type}`, @@ -88,7 +88,7 @@ export const MenuItemLi = withProps<{ depth: number }>(styled.li)` `; export const menuItemDepth = { - '0': css` + 0: css` opacity: 0.7; text-transform: uppercase; font-size: 0.8em; @@ -96,14 +96,14 @@ export const menuItemDepth = { cursor: default; color: ${props => props.theme.colors.text}; `, - '1': css` + 1: css` font-size: 0.929em; text-transform: uppercase; &:hover { color: ${props => props.theme.colors.main}; } `, - '2': css` + 2: css` color: ${props => props.theme.colors.text}; `, }; diff --git a/src/components/SourceCode/SourceCode.tsx b/src/components/SourceCode/SourceCode.tsx index 5bdb7c97..f8278a68 100644 --- a/src/components/SourceCode/SourceCode.tsx +++ b/src/components/SourceCode/SourceCode.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { highlight } from '../../utils'; import styled from '../../styled-components'; +import { highlight } from '../../utils'; const StyledPre = styled.pre` font-family: ${props => props.theme.code.fontFamily}; diff --git a/src/components/StickySidebar/StickySidebar.tsx b/src/components/StickySidebar/StickySidebar.tsx index d057b476..5d327045 100644 --- a/src/components/StickySidebar/StickySidebar.tsx +++ b/src/components/StickySidebar/StickySidebar.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import { ComponentWithOptions } from '../OptionsProvider'; import { RedocNormalizedOptions, RedocRawOptions } from '../../services/RedocNormalizedOptions'; import styled from '../../styled-components'; +import { ComponentWithOptions } from '../OptionsProvider'; let Stickyfill; if (typeof window !== 'undefined') { @@ -34,11 +34,15 @@ export class StickySidebar extends ComponentWithOptions { stickyElement: Element; componentDidMount() { - stickyfill && stickyfill.add(this.stickyElement); + if (stickyfill) { + stickyfill.add(this.stickyElement); + } } componentWillUnmount() { - stickyfill && stickyfill.remove(this.stickyElement); + if (stickyfill) { + stickyfill.remove(this.stickyElement); + } } get scrollYOffset() { @@ -52,7 +56,7 @@ export class StickySidebar extends ComponentWithOptions { } render() { - let top = this.scrollYOffset; + const top = this.scrollYOffset; const height = `calc(100vh - ${top})`; @@ -60,6 +64,7 @@ export class StickySidebar extends ComponentWithOptions { { this.stickyElement = el; }} diff --git a/src/components/StoreProvider.ts b/src/components/StoreProvider.ts index 441c6527..3d5f332e 100644 --- a/src/components/StoreProvider.ts +++ b/src/components/StoreProvider.ts @@ -1,8 +1,8 @@ import { Component } from 'react'; import { AppStore } from '../services/'; -import { loadAndBundleSpec } from '../utils'; import { RedocRawOptions } from '../services/RedocNormalizedOptions'; +import { loadAndBundleSpec } from '../utils'; interface StoreProviderProps { specUrl?: string; @@ -36,7 +36,7 @@ export class StoreProvider extends Componentdocument.body).createTextRange) { - range = (document.body).createTextRange(); + if ((document.body as any).createTextRange) { + range = (document.body as any).createTextRange(); range.moveToElementText(element); range.select(); } else if (document.createRange && window.getSelection) { @@ -25,8 +25,8 @@ export class ClipboardService { } static deselect(): void { - if ((document).selection) { - (document).selection.empty(); + if ((document as any).selection) { + (document as any).selection.empty(); } else if (window.getSelection) { window.getSelection().removeAllRanges(); } @@ -44,13 +44,15 @@ export class ClipboardService { static copyElement(element: any): boolean { ClipboardService.selectElement(element); - let res = ClipboardService.copySelected(); - if (res) ClipboardService.deselect(); + const res = ClipboardService.copySelected(); + if (res) { + ClipboardService.deselect(); + } return res; } static copyCustom(text: string): boolean { - let textArea = document.createElement('textarea'); + const textArea = document.createElement('textarea'); textArea.style.position = 'fixed'; textArea.style.top = '0'; textArea.style.left = '0'; @@ -77,7 +79,7 @@ export class ClipboardService { textArea.select(); - let res = ClipboardService.copySelected(); + const res = ClipboardService.copySelected(); document.body.removeChild(textArea); return res; diff --git a/src/services/HistoryService.ts b/src/services/HistoryService.ts index 9d1cdb93..ab80869d 100644 --- a/src/services/HistoryService.ts +++ b/src/services/HistoryService.ts @@ -8,7 +8,7 @@ function isSameHash(a: string, b: string): boolean { return a === b || '#' + a === b || a === '#' + b; } -class _HistoryService { +class IntHistoryService { private causedHashChange: boolean = false; private _emiter; @@ -50,7 +50,9 @@ class _HistoryService { @bind @debounce 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 (isBrowser) { 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) { module.hot.dispose(() => { diff --git a/src/services/MarkdownRenderer.ts b/src/services/MarkdownRenderer.ts index 16dcfa7f..4b51381f 100644 --- a/src/services/MarkdownRenderer.ts +++ b/src/services/MarkdownRenderer.ts @@ -1,9 +1,9 @@ import * as Remarkable from 'remarkable'; import { MDComponent } from '../components/Markdown/Markdown'; +import { highlight, html2Str } from '../utils'; import { IMenuItem, SECTION_ATTR } from './MenuStore'; import { GroupModel } from './models'; -import { highlight, html2Str } from '../utils'; const md = new Remarkable('default', { html: true, @@ -20,14 +20,14 @@ export function buildComponentComment(name: string) { return ``; } -type MarkdownHeading = { +interface MarkdownHeading { name: string; children?: MarkdownHeading[]; content?: string; -}; +} export class MarkdownRenderer { - public headings: GroupModel[] = []; + headings: GroupModel[] = []; currentTopHeading: GroupModel; private _origRules: any = {}; @@ -52,9 +52,11 @@ export class MarkdownRenderer { } flattenHeadings(container?: MarkdownHeading[]): MarkdownHeading[] { - if (container === undefined) return []; - let res: MarkdownHeading[] = []; - for (let heading of container) { + if (container === undefined) { + return []; + } + const res: MarkdownHeading[] = []; + for (const heading of container) { res.push(heading); res.push(...this.flattenHeadings(heading.children)); } @@ -64,14 +66,16 @@ export class MarkdownRenderer { attachHeadingsContent(rawText: string) { const buildRegexp = heading => new RegExp(``); - let flatHeadings = this.flattenHeadings(this.headings); - if (flatHeadings.length < 1) return; + const flatHeadings = this.flattenHeadings(this.headings); + if (flatHeadings.length < 1) { + return; + } let prevHeading = flatHeadings[0]; let prevPos = rawText.search(buildRegexp(prevHeading)); for (let i = 1; i < flatHeadings.length; i++) { - let heading = flatHeadings[i]; - let currentPos = rawText.substr(prevPos + 1).search(buildRegexp(heading)) + prevPos + 1; + const heading = flatHeadings[i]; + const currentPos = rawText.substr(prevPos + 1).search(buildRegexp(heading)) + prevPos + 1; prevHeading.content = html2Str(rawText.substring(prevPos, currentPos)); prevHeading = heading; @@ -84,17 +88,17 @@ export class MarkdownRenderer { if (tokens[idx].hLevel > 2) { return this._origRules.open(tokens, idx); } else { - let content = tokens[idx + 1].content; + const content = tokens[idx + 1].content; if (tokens[idx].hLevel === 1) { this.currentTopHeading = this.saveHeading(content); - let id = this.currentTopHeading.id; + const id = this.currentTopHeading.id; return ( `` + `` + `` ); } else if (tokens[idx].hLevel === 2) { - let { id } = this.saveHeading(content, this.currentTopHeading.items); + const { id } = this.saveHeading(content, this.currentTopHeading.items); return ( `` + `` + @@ -119,9 +123,9 @@ export class MarkdownRenderer { 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); @@ -142,17 +146,18 @@ export class MarkdownRenderer { rawText: string, components: Dict, raw: boolean = true, - ): (string | MDComponent)[] { - let componentDefs: string[] = []; - let match; - let anyCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '(.*?)'), 'gmi'); - while ((match = anyCompRegexp.exec(rawText))) { + ): Array { + const componentDefs: string[] = []; + const anyCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '(.*?)'), 'gmi'); + let match = anyCompRegexp.exec(rawText); + while (match) { componentDefs.push(match[1]); + match = anyCompRegexp.exec(rawText); } - let splitCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '.*?'), 'mi'); - let htmlParts = rawText.split(splitCompRegexp); - let res: any[] = []; + const splitCompRegexp = new RegExp(COMPONENT_REGEXP.replace('{component}', '.*?'), 'mi'); + const htmlParts = rawText.split(splitCompRegexp); + const res: any[] = []; for (let i = 0; i < htmlParts.length; i++) { const htmlPart = htmlParts[i]; if (htmlPart) { @@ -160,10 +165,12 @@ export class MarkdownRenderer { } if (componentDefs[i]) { const { componentName, attrs } = parseComponent(componentDefs[i]); - if (!componentName) continue; + if (!componentName) { + continue; + } res.push({ ...components[componentName], - attrs: attrs, + attrs, }); } } @@ -178,7 +185,9 @@ function parseComponent( attrs: any; } { 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]; return { componentName, diff --git a/src/services/MenuBuilder.ts b/src/services/MenuBuilder.ts index db6cd576..addb9853 100644 --- a/src/services/MenuBuilder.ts +++ b/src/services/MenuBuilder.ts @@ -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 { isOperationName, JsonPointer } from '../utils'; import { MarkdownRenderer } from './MarkdownRenderer'; +import { GroupModel, OperationModel } from './models'; +import { OpenAPIParser } from './OpenAPIParser'; import { RedocNormalizedOptions } from './RedocNormalizedOptions'; export type TagInfo = OpenAPITag & { @@ -13,7 +13,7 @@ export type TagInfo = OpenAPITag & { export type ExtendedOpenAPIOperation = { _$ref: string; httpVerb: string; - pathParameters: Referenced[]; + pathParameters: Array>; } & OpenAPIOperation; export type TagsInfoMap = Dict; @@ -70,9 +70,9 @@ export class MenuBuilder { tags: TagsInfoMap, options: RedocNormalizedOptions, ): GroupModel[] { - let res: GroupModel[] = []; - for (let group of groups) { - let item = new GroupModel('group', group, parent); + const res: GroupModel[] = []; + for (const group of groups) { + const item = new GroupModel('group', group, parent); item.depth = GROUP_DEPTH; item.items = MenuBuilder.getTagsItems(parser, tags, item, group, options); res.push(item); @@ -111,16 +111,18 @@ export class MenuBuilder { return tagsMap[tagName]; }); - let res: (GroupModel | OperationModel)[] = []; - for (let tag of tags) { - if (!tag) continue; - let item = new GroupModel('tag', tag, parent); + const res: Array = []; + for (const tag of tags) { + if (!tag) { + continue; + } + const item = new GroupModel('tag', tag, parent); item.depth = GROUP_DEPTH + 1; item.items = this.getOperationsItems(parser, item, tag, item.depth + 1, options); // don't put empty tag into content, instead put its operations 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); continue; } @@ -147,9 +149,9 @@ export class MenuBuilder { return []; } - let res: OperationModel[] = []; - for (let operationInfo of tag.operations) { - let operation = new OperationModel(parser, operationInfo, parent, options); + const res: OperationModel[] = []; + for (const operationInfo of tag.operations) { + const operation = new OperationModel(parser, operationInfo, parent, options); operation.depth = depth; res.push(operation); } @@ -161,16 +163,15 @@ export class MenuBuilder { */ static getTagsWithOperations(spec: OpenAPISpec): TagsInfoMap { const tags: TagsInfoMap = {}; - for (let tag of spec.tags || []) { - tags[tag.name] = Object.assign(tag); - tags[tag.name].operations = []; + for (const tag of spec.tags || []) { + tags[tag.name] = { ...tag, operations: [] }; } const paths = spec.paths; - for (let pathName of Object.keys(paths)) { + for (const pathName of Object.keys(paths)) { const path = paths[pathName]; const operations = Object.keys(path).filter(isOperationName); - for (let operationName of operations) { + for (const operationName of operations) { const operationInfo = path[operationName]; let operationTags = operationInfo.tags; @@ -179,7 +180,7 @@ export class MenuBuilder { operationTags = ['']; } const operationPointer = JsonPointer.compile(['paths', pathName, operationName]); - for (let tagName of operationTags) { + for (const tagName of operationTags) { let tag = tags[tagName]; if (tag === undefined) { tag = { @@ -188,7 +189,9 @@ export class MenuBuilder { }; tags[tagName] = tag; } - if (tag['x-traitTag']) continue; + if (tag['x-traitTag']) { + continue; + } tag.operations.push({ ...operationInfo, _$ref: operationPointer, diff --git a/src/services/MenuStore.ts b/src/services/MenuStore.ts index 76e0eda7..8fea6b01 100644 --- a/src/services/MenuStore.ts +++ b/src/services/MenuStore.ts @@ -1,12 +1,12 @@ +import { action, computed } from 'mobx'; import { querySelector } from '../utils/dom'; -import { OperationModel, GroupModel, SpecStore } from './models'; -import { computed, action } from 'mobx'; +import { GroupModel, OperationModel, SpecStore } from './models'; -import { ScrollService } from './ScrollService'; import { HistoryService } from './HistoryService'; +import { ScrollService } from './ScrollService'; -import { GROUP_DEPTH } from './MenuBuilder'; import { flattenByProp } from '../utils'; +import { GROUP_DEPTH } from './MenuBuilder'; export type MenuItemGroupType = 'group' | 'tag' | 'section'; export type MenuItemType = MenuItemGroupType | 'operation'; @@ -18,7 +18,7 @@ export interface IMenuItem { name: string; depth: number; active: boolean; - items: Array; + items: IMenuItem[]; parent?: IMenuItem; deprecated?: boolean; type: MenuItemType; @@ -34,18 +34,18 @@ export const SECTION_ATTR = 'data-section-id'; * Stores all side-menu related information */ 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 */ activeItemIdx: number = -1; + /** + * cached flattened menu items to support absolute indexing + */ + private _unsubscribe: () => void; + private _hashUnsubscribe: () => void; + private _items?: Array; + /** * * @param spec [SpecStore](#SpecStore) which contains page content structure @@ -107,13 +107,15 @@ export class MenuStore { */ @action.bound updateOnHash(hash: string = HistoryService.hash): boolean { - if (!hash) return false; + if (!hash) { + return false; + } let item: IMenuItem | undefined; hash = hash.substr(1); - let namespace = hash.split('/')[0]; + const namespace = hash.split('/')[0]; let ptr = decodeURIComponent(hash.substr(namespace.length + 1)); if (namespace === 'section' || namespace === 'tag') { - let sectionId = ptr.split('/')[0]; + const sectionId = ptr.split('/')[0]; ptr = ptr.substr(sectionId.length); let searchId; @@ -123,14 +125,14 @@ export class MenuStore { searchId = ptr || namespace + '/' + sectionId; } - item = this.flatItems.find(item => item.id === searchId); + item = this.flatItems.find(i => i.id === searchId); if (item === undefined) { this._scrollService.scrollIntoViewBySelector(`[${SECTION_ATTR}="${searchId}"]`); return false; } } else if (namespace === 'operation') { - item = this.flatItems.find(item => { - return (item as OperationModel).operationId === ptr; + item = this.flatItems.find(i => { + return (i as OperationModel).operationId === ptr; }); } if (item) { @@ -219,7 +221,11 @@ export class MenuStore { * @see MenuStore.activate */ @action - activateAndScroll(item: IMenuItem | undefined, updateHash: boolean, rewriteHistory?: boolean) { + activateAndScroll( + item: IMenuItem | undefined, + updateHash: boolean, + rewriteHistory?: boolean, + ) { this.activate(item, updateHash, rewriteHistory); this.scrollToActive(); } diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts index bbd235f9..618bc1ee 100644 --- a/src/services/OpenAPIParser.ts +++ b/src/services/OpenAPIParser.ts @@ -3,11 +3,11 @@ import { resolve as urlResolve } from 'url'; import { OpenAPIRef, OpenAPISchema, OpenAPISpec, Referenced } from '../types'; +import { appendToMdHeading, isBrowser } from '../utils/'; import { JsonPointer } from '../utils/JsonPointer'; import { isNamedDefinition } from '../utils/openapi'; -import { COMPONENT_REGEXP, buildComponentComment } from './MarkdownRenderer'; +import { buildComponentComment, COMPONENT_REGEXP } from './MarkdownRenderer'; import { RedocNormalizedOptions } from './RedocNormalizedOptions'; -import { appendToMdHeading, isBrowser } from '../utils/'; export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] }; @@ -16,7 +16,7 @@ export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] }; * endless recursion because of circular refs */ class RefCounter { - public _counter = {}; + _counter = {}; reset(): void { this._counter = {}; @@ -42,6 +42,8 @@ export class OpenAPIParser { @observable specUrl: string; @observable.ref spec: OpenAPISpec; + private _refCounter: RefCounter = new RefCounter(); + constructor( spec: OpenAPISpec, specUrl: string | undefined, @@ -60,8 +62,6 @@ export class OpenAPIParser { } } - private _refCounter: RefCounter = new RefCounter(); - validate(spec: any) { if (spec.openapi === undefined) { throw new Error('Document must be valid OpenAPI 3.0.0 definition'); @@ -93,8 +93,12 @@ export class OpenAPIParser { */ byRef = (ref: string): T | undefined => { let res; - if (this.spec === undefined) return; - if (ref.charAt(0) !== '#') ref = '#' + ref; + if (!this.spec) { + return; + } + if (ref.charAt(0) !== '#') { + ref = '#' + ref; + } ref = decodeURIComponent(ref); try { res = JsonPointer.get(this.spec, ref); @@ -120,7 +124,7 @@ export class OpenAPIParser { resetVisited() { if (__DEV__) { // check in dev mode - for (let k in this._refCounter._counter) { + for (const k in this._refCounter._counter) { if (this._refCounter._counter[k] > 0) { console.warn('Not exited reference: ' + k); } @@ -130,7 +134,9 @@ export class OpenAPIParser { } exitRef(ref: Referenced) { - if (!this.isRef(ref)) return; + if (!this.isRef(ref)) { + return; + } this._refCounter.exit(ref.$ref); } @@ -146,6 +152,7 @@ export class OpenAPIParser { this._refCounter.visit(obj.$ref); if (visited && !forceCircular) { // circular reference detected + // tslint:disable-next-line return Object.assign({}, resolved, { 'x-circular-ref': true }); } // 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 ( receiver.type !== subSchema.type && receiver.type !== undefined && @@ -244,7 +251,7 @@ export class OpenAPIParser { findDerived($refs: string[]): Dict { const res: Dict = {}; 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]); if ( def.allOf !== undefined && diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts index a25a9520..eceb1057 100644 --- a/src/services/RedocNormalizedOptions.ts +++ b/src/services/RedocNormalizedOptions.ts @@ -1,11 +1,10 @@ -import { ThemeInterface } from '../theme'; -import { isNumeric, mergeObjects } from '../utils/helpers'; +import defaultTheme, { ThemeInterface } from '../theme'; import { querySelector } from '../utils/dom'; -import defaultTheme from '../theme'; +import { isNumeric, mergeObjects } from '../utils/helpers'; export interface RedocRawOptions { theme?: ThemeInterface; - scrollYOffset?: number | string | Function; + scrollYOffset?: number | string | (() => number); hideHostname?: boolean | string; expandResponses?: string | 'all'; requiredPropsFirst?: boolean | string; @@ -17,34 +16,16 @@ export interface RedocRawOptions { } function argValueToBoolean(val?: string | boolean): boolean { - if (val === undefined) return false; - if (typeof val === 'string') return true; + if (val === undefined) { + return false; + } + if (typeof val === 'string') { + return true; + } return val; } 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']) { if (value === 'all') { return 'all'; @@ -98,4 +79,26 @@ export class RedocNormalizedOptions { 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); + } } diff --git a/src/services/ScrollService.ts b/src/services/ScrollService.ts index 54f82bee..49b2e939 100644 --- a/src/services/ScrollService.ts +++ b/src/services/ScrollService.ts @@ -1,7 +1,7 @@ -import { debounce, bind } from 'decko'; +import { bind, debounce } from 'decko'; import { EventEmitter } from 'eventemitter3'; -import { querySelector, isBrowser } from '../utils'; +import { isBrowser, querySelector } from '../utils'; import { RedocNormalizedOptions } from './RedocNormalizedOptions'; const EVENT = 'scroll'; @@ -18,11 +18,15 @@ export class ScrollService { bind() { this._prevOffsetY = this.scrollY(); - this._scrollParent && this._scrollParent.addEventListener('scroll', this.handleScroll); + if (this._scrollParent) { + this._scrollParent.addEventListener('scroll', this.handleScroll); + } } dispose() { - this._scrollParent && this._scrollParent.removeEventListener('scroll', this.handleScroll); + if (this._scrollParent) { + this._scrollParent.removeEventListener('scroll', this.handleScroll); + } this._emiter.removeAllListeners(EVENT); } @@ -37,12 +41,16 @@ export class ScrollService { } isElementBellow(el: Element | null) { - if (el === null) return; + if (el === null) { + return; + } return el.getBoundingClientRect().top > this.options.scrollYOffset(); } isElementAbove(el: Element | null) { - if (el === null) return; + if (el === null) { + return; + } return Math.trunc(el.getBoundingClientRect().top) <= this.options.scrollYOffset(); } @@ -56,9 +64,9 @@ export class ScrollService { return; } element.scrollIntoView(); - this._scrollParent && - this._scrollParent.scrollBy && + if (this._scrollParent && this._scrollParent.scrollBy) { (this._scrollParent.scrollBy as any)(0, -this.options.scrollYOffset()); + } } scrollIntoViewBySelector(selector: string) { diff --git a/src/services/SpecStore.ts b/src/services/SpecStore.ts index 749c36ed..cde6e274 100644 --- a/src/services/SpecStore.ts +++ b/src/services/SpecStore.ts @@ -1,13 +1,13 @@ +import { computed, observable } from 'mobx'; import { OpenAPISpec } from '../types'; -import { observable, computed } from 'mobx'; // import { OpenAPIExternalDocumentation, OpenAPIInfo } from '../types'; import { MenuBuilder } from './MenuBuilder'; -import { OpenAPIParser } from './OpenAPIParser'; import { ApiInfoModel } from './models/ApiInfo'; -import { RedocNormalizedOptions } from './RedocNormalizedOptions'; 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 */ diff --git a/src/services/models/ApiInfo.ts b/src/services/models/ApiInfo.ts index 8e82fd55..12f1e87c 100644 --- a/src/services/models/ApiInfo.ts +++ b/src/services/models/ApiInfo.ts @@ -1,6 +1,6 @@ import { OpenAPIContact, OpenAPIInfo, OpenAPILicense } from '../../types'; -import { OpenAPIParser } from '../OpenAPIParser'; import { isBrowser } from '../../utils/'; +import { OpenAPIParser } from '../OpenAPIParser'; export class ApiInfoModel implements OpenAPIInfo { title: string; diff --git a/src/services/models/Example.ts b/src/services/models/Example.ts index 01ce3893..f043bccd 100644 --- a/src/services/models/Example.ts +++ b/src/services/models/Example.ts @@ -1,4 +1,4 @@ -import { Referenced, OpenAPIExample } from '../../types'; +import { OpenAPIExample, Referenced } from '../../types'; import { OpenAPIParser } from '../OpenAPIParser'; export class ExampleModel { diff --git a/src/services/models/Field.ts b/src/services/models/Field.ts index 1fc900cf..8b2f29a2 100644 --- a/src/services/models/Field.ts +++ b/src/services/models/Field.ts @@ -1,24 +1,24 @@ -import { observable, action } from 'mobx'; +import { action, observable } from 'mobx'; import { OpenAPIParameter, Referenced } from '../../types'; import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; -import { SchemaModel } from './Schema'; import { OpenAPIParser } from '../OpenAPIParser'; +import { SchemaModel } from './Schema'; /** * Field or Parameter model ready to be used by components */ export class FieldModel { - @observable public expanded: boolean = false; + @observable expanded: boolean = false; - public schema: SchemaModel; - public name: string; - public required: boolean; - public description: string; - public example?: string; - public deprecated: boolean; - public in?: string; + schema: SchemaModel; + name: string; + required: boolean; + description: string; + example?: string; + deprecated: boolean; + in?: string; constructor( parser: OpenAPIParser, diff --git a/src/services/models/Group.model.ts b/src/services/models/Group.model.ts index da2348b3..89d4e878 100644 --- a/src/services/models/Group.model.ts +++ b/src/services/models/Group.model.ts @@ -1,11 +1,10 @@ -import { observable, action } from 'mobx'; +import { action, observable } from 'mobx'; +import slugify from 'slugify'; import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types'; import { ContentItemModel } from '../MenuBuilder'; import { IMenuItem, MenuItemGroupType } from '../MenuStore'; -const slugify = require('slugify'); - /** * Operations Group model ready to be used by components */ @@ -17,7 +16,7 @@ export class GroupModel implements IMenuItem { description?: string; type: MenuItemGroupType; - items: Array = []; + items: ContentItemModel[] = []; parent?: GroupModel; externalDocs?: OpenAPIExternalDocumentation; @@ -48,7 +47,9 @@ export class GroupModel implements IMenuItem { @action deactivate() { // disallow deactivating groups - if (this.type === 'group') return; + if (this.type === 'group') { + return; + } this.active = false; } diff --git a/src/services/models/MediaContent.ts b/src/services/models/MediaContent.ts index e943755a..bd126a21 100644 --- a/src/services/models/MediaContent.ts +++ b/src/services/models/MediaContent.ts @@ -1,10 +1,10 @@ -import { observable, action, computed } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { OpenAPIMediaType } from '../../types'; import { MediaTypeModel } from './MediaType'; -import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; import { OpenAPIParser } from '../OpenAPIParser'; +import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; /** * MediaContent model ready to be sued by React components diff --git a/src/services/models/MediaType.ts b/src/services/models/MediaType.ts index 00c12f8f..3521ba4d 100644 --- a/src/services/models/MediaType.ts +++ b/src/services/models/MediaType.ts @@ -1,10 +1,10 @@ import * as Sampler from 'openapi-sampler'; import { OpenAPIExample, OpenAPIMediaType } from '../../types'; -import { SchemaModel } from './Schema'; import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; +import { SchemaModel } from './Schema'; -import { mapValues, isJsonLike } from '../../utils'; +import { isJsonLike, mapValues } from '../../utils'; import { OpenAPIParser } from '../OpenAPIParser'; import { ExampleModel } from './Example'; @@ -39,14 +39,13 @@ export class MediaTypeModel { } generateExample(parser: OpenAPIParser, info: OpenAPIMediaType) { - const { schema, isRequestType } = this; - if (schema && schema.oneOf) { + if (this.schema && this.schema.oneOf) { this.examples = {}; - for (let subSchema of schema.oneOf) { + for (const subSchema of this.schema.oneOf) { this.examples[subSchema.title] = { value: Sampler.sample( subSchema.rawSchema, - { skipReadOnly: isRequestType, skipReadWrite: !isRequestType }, + { skipReadOnly: this.isRequestType, skipReadWrite: !this.isRequestType }, parser.spec, ), }; @@ -56,7 +55,7 @@ export class MediaTypeModel { default: new ExampleModel(parser, { value: Sampler.sample( info.schema, - { skipReadOnly: isRequestType, skipReadWrite: !isRequestType }, + { skipReadOnly: this.isRequestType, skipReadWrite: !this.isRequestType }, parser.spec, ), }), diff --git a/src/services/models/Operation.ts b/src/services/models/Operation.ts index e22437b8..846bfd62 100644 --- a/src/services/models/Operation.ts +++ b/src/services/models/Operation.ts @@ -1,21 +1,21 @@ -import { observable, action } from 'mobx'; +import { action, observable } from 'mobx'; import { join as joinPaths } from 'path'; import { parse as urlParse } from 'url'; import { IMenuItem } from '../MenuStore'; -import { SecurityRequirementModel } from './SecurityRequirement'; import { GroupModel } from './Group.model'; +import { SecurityRequirementModel } from './SecurityRequirement'; import { OpenAPIExternalDocumentation, OpenAPIServer } from '../../types'; -import { FieldModel } from './Field'; -import { ResponseModel } from './Response'; -import { RequestBodyModel } from './RequestBody'; -import { CodeSample } from './types'; -import { OpenAPIParser } from '../OpenAPIParser'; +import { getOperationSummary, isAbsolutePath, JsonPointer, stripTrailingSlash } from '../../utils'; import { ContentItemModel, ExtendedOpenAPIOperation } from '../MenuBuilder'; -import { JsonPointer, getOperationSummary, isAbsolutePath, stripTrailingSlash } from '../../utils'; +import { OpenAPIParser } from '../OpenAPIParser'; 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 @@ -30,7 +30,7 @@ export class OperationModel implements IMenuItem { parent?: GroupModel; externalDocs?: OpenAPIExternalDocumentation; - items: Array = []; + items: ContentItemModel[] = []; depth: number; @@ -80,7 +80,7 @@ export class OperationModel implements IMenuItem { let hasSuccessResponses = false; this.responses = Object.keys(operationSpec.responses || []) .filter(code => { - if (parseInt(code) >= 100 && parseInt(code) <= 399) { + if (parseInt(code, 10) >= 100 && parseInt(code, 10) <= 399) { hasSuccessResponses = true; } return isNumeric(code) || code === 'default'; diff --git a/src/services/models/RequestBody.ts b/src/services/models/RequestBody.ts index f9ed68f0..f3b45959 100644 --- a/src/services/models/RequestBody.ts +++ b/src/services/models/RequestBody.ts @@ -1,8 +1,8 @@ import { OpenAPIRequestBody, Referenced } from '../../types'; -import { MediaContentModel } from './MediaContent'; import { OpenAPIParser } from '../OpenAPIParser'; import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; +import { MediaContentModel } from './MediaContent'; export class RequestBodyModel { description: string; diff --git a/src/services/models/Response.ts b/src/services/models/Response.ts index 066e10a6..3f8937cd 100644 --- a/src/services/models/Response.ts +++ b/src/services/models/Response.ts @@ -1,21 +1,21 @@ -import { observable, action } from 'mobx'; +import { action, observable } from 'mobx'; import { OpenAPIResponse, Referenced } from '../../types'; +import { getStatusCodeType } from '../../utils'; +import { OpenAPIParser } from '../OpenAPIParser'; +import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; import { FieldModel } from './Field'; import { MediaContentModel } from './MediaContent'; -import { OpenAPIParser } from '../OpenAPIParser'; -import { getStatusCodeType } from '../../utils'; -import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; export class ResponseModel { - @observable public expanded: boolean; + @observable expanded: boolean; - public content?: MediaContentModel; - public code: string; - public description: string; - public type: string; - public headers: FieldModel[] = []; + content?: MediaContentModel; + code: string; + description: string; + type: string; + headers: FieldModel[] = []; constructor( parser: OpenAPIParser, diff --git a/src/services/models/Schema.ts b/src/services/models/Schema.ts index 7e9f39a6..dda8eabc 100644 --- a/src/services/models/Schema.ts +++ b/src/services/models/Schema.ts @@ -1,11 +1,12 @@ -import { observable, action } from 'mobx'; +import { action, observable } from 'mobx'; import { OpenAPISchema, Referenced } from '../../types'; -import { FieldModel } from './Field'; import { OpenAPIParser } from '../OpenAPIParser'; import { RedocNormalizedOptions } from '../RedocNormalizedOptions'; +import { FieldModel } from './Field'; +import { MergedOpenAPISchema } from '../'; import { detectType, humanizeConstraints, @@ -13,7 +14,6 @@ import { isPrimitiveType, JsonPointer, } from '../../utils/'; -import { MergedOpenAPISchema } from '../'; // TODO: refactor this model, maybe use getters instead of copying all the values export class SchemaModel { @@ -69,9 +69,9 @@ export class SchemaModel { 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 - parser.exitRef({ $ref }); + parser.exitRef({ $ref: parent$ref }); } } @@ -174,23 +174,25 @@ export class SchemaModel { const derived = parser.findDerived([...(schema.namedParents || []), this._$ref]); if (schema.oneOf) { - for (let variant of schema.oneOf) { - if (variant.$ref === undefined) continue; + for (const variant of schema.oneOf) { + if (variant.$ref === undefined) { + continue; + } const name = JsonPointer.dirName(variant.$ref); derived[variant.$ref] = name; } } const mapping = schema.discriminator!.mapping || {}; - for (let name in mapping) { + for (const name in mapping) { derived[mapping[name]] = name; } const refs = Object.keys(derived); this.oneOf = refs.map(ref => { - const schema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true); - schema.title = derived[ref]; - return schema; + const innerSchema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true); + innerSchema.title = derived[ref]; + return innerSchema; }); } } diff --git a/src/services/models/SecurityRequirement.ts b/src/services/models/SecurityRequirement.ts index 2e41f97e..2a2a601c 100644 --- a/src/services/models/SecurityRequirement.ts +++ b/src/services/models/SecurityRequirement.ts @@ -1,14 +1,14 @@ import { OpenAPISecurityRequirement } from '../../types'; -import { OpenAPIParser } from '../OpenAPIParser'; import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi'; +import { OpenAPIParser } from '../OpenAPIParser'; export class SecurityRequirementModel { - schemes: { + schemes: Array<{ id: string; sectionId: string; type: string; scopes: string[]; - }[]; + }>; constructor(requirement: OpenAPISecurityRequirement, parser: OpenAPIParser) { const schemes = (parser.spec.components && parser.spec.components.securitySchemes) || {}; diff --git a/src/services/models/SecuritySchemes.ts b/src/services/models/SecuritySchemes.ts index a90bab16..7b8452be 100644 --- a/src/services/models/SecuritySchemes.ts +++ b/src/services/models/SecuritySchemes.ts @@ -1,6 +1,6 @@ import { OpenAPISecurityScheme, Referenced } from '../../types'; -import { OpenAPIParser } from '../OpenAPIParser'; import { SECURITY_SCHEMES_SECTION } from '../../utils/openapi'; +import { OpenAPIParser } from '../OpenAPIParser'; export class SecuritySchemeModel { id: string; diff --git a/src/services/models/types.ts b/src/services/models/types.ts index a53b5359..f91347f7 100644 --- a/src/services/models/types.ts +++ b/src/services/models/types.ts @@ -1,4 +1,4 @@ -export type CodeSample = { +export interface CodeSample { lang: string; source: string; -}; +} diff --git a/src/standalone.tsx b/src/standalone.tsx index 6762b1c9..746d6263 100644 --- a/src/standalone.tsx +++ b/src/standalone.tsx @@ -1,17 +1,18 @@ -import { render } from 'react-dom'; import * as React from 'react'; +import { render } from 'react-dom'; -import { querySelector } from './utils/dom'; import { RedocStandalone } from './components/RedocStandalone'; +import { querySelector } from './utils/dom'; export const version = __REDOC_VERSION__; export const revision = __REDOC_REVISION__; function attributesMap(element: Element) { - var res = {}; - var elAttrs = element.attributes; + const res = {}; + const elAttrs = element.attributes; + // tslint:disable-next-line for (let i = 0; i < elAttrs.length; i++) { - var attrib = elAttrs[i]; + const attrib = elAttrs[i]; res[attrib.name] = attrib.value; } return res; @@ -20,7 +21,7 @@ function attributesMap(element: Element) { function parseOptionsFromElement(element: Element) { const attrMap = attributesMap(element); const res = {}; - for (let attrName in attrMap) { + for (const attrName in attrMap) { const optionName = attrName.replace(/-(.)/g, (_, $1) => $1.toUpperCase()); res[optionName] = attrMap[attrName]; // TODO: normalize options diff --git a/src/styled-components.ts b/src/styled-components.ts index 187bdbb8..6f35e52a 100644 --- a/src/styled-components.ts +++ b/src/styled-components.ts @@ -1,5 +1,4 @@ import * as styledComponents from 'styled-components'; -import { ThemedStyledComponentsModule } from 'styled-components'; import { ThemeInterface } from './theme'; @@ -18,9 +17,9 @@ const { keyframes, ThemeProvider, withTheme, -} = (styledComponents as ThemedStyledComponentsModule) as ThemedStyledComponentsModule< - ThemeInterface ->; +} = (styledComponents as styledComponents.ThemedStyledComponentsModule< + any +>) as styledComponents.ThemedStyledComponentsModule; export { css, injectGlobal, keyframes, ThemeProvider, withTheme, withProps }; export default styled; diff --git a/src/types/open-api.ts b/src/types/open-api.ts index 0355519b..92202e8e 100644 --- a/src/types/open-api.ts +++ b/src/types/open-api.ts @@ -1,6 +1,6 @@ import { Omit } from './'; -export type OpenAPISpec = { +export interface OpenAPISpec { openapi: string; info: OpenAPIInfo; servers?: OpenAPIServer[]; @@ -9,7 +9,7 @@ export type OpenAPISpec = { security?: OpenAPISecurityRequirement[]; tags?: OpenAPITag[]; externalDocs?: OpenAPIExternalDocumentation; -}; +} export interface OpenAPIInfo { title: string; @@ -21,59 +21,58 @@ export interface OpenAPIInfo { license?: OpenAPILicense; } -export type OpenAPIServer = { +export interface OpenAPIServer { url: string; description?: string; variables?: { [name: string]: OpenAPIServerVariable }; -}; +} -export type OpenAPIServerVariable = { +export interface OpenAPIServerVariable { enum?: string[]; default: string; description?: string; -}; +} -export type OpenAPIPaths = { [path: string]: OpenAPIPath }; -export type OpenAPIRef = { +export interface OpenAPIPaths { + [path: string]: OpenAPIPath; +} +export interface OpenAPIRef { $ref: string; -}; +} export type Referenced = OpenAPIRef | T; -export type OpenAPIPath = - // | OpenAPIRef // paths can't be external in redoc because they are prebundled - // | { - { - summary?: string; - description?: string; - get?: OpenAPIOperation; - put?: OpenAPIOperation; - post?: OpenAPIOperation; - delete?: OpenAPIOperation; - options?: OpenAPIOperation; - head?: OpenAPIOperation; - patch?: OpenAPIOperation; - trace?: OpenAPIOperation; - servers?: OpenAPIServer[]; - parameters?: Referenced[]; - }; +export interface OpenAPIPath { + summary?: string; + description?: string; + get?: OpenAPIOperation; + put?: OpenAPIOperation; + post?: OpenAPIOperation; + delete?: OpenAPIOperation; + options?: OpenAPIOperation; + head?: OpenAPIOperation; + patch?: OpenAPIOperation; + trace?: OpenAPIOperation; + servers?: OpenAPIServer[]; + parameters?: Array>; +} -export type OpenAPIOperation = { +export interface OpenAPIOperation { tags?: string[]; summary?: string; description?: string; externalDocs?: OpenAPIExternalDocumentation; operationId?: string; - parameters?: Referenced[]; + parameters?: Array>; requestBody?: Referenced; responses: OpenAPIResponses; callbacks?: { [name: string]: Referenced }; deprecated?: boolean; security?: OpenAPISecurityRequirement[]; servers?: OpenAPIServer[]; -}; +} -export type OpenAPIParameter = { +export interface OpenAPIParameter { name: string; in?: OpenAPIParameterLocation; description?: string; @@ -87,16 +86,16 @@ export type OpenAPIParameter = { example?: any; examples?: { [media: string]: Referenced }; content?: { [media: string]: OpenAPIMediaType }; -}; +} -export type OpenAPIExample = { +export interface OpenAPIExample { value: any; summary?: string; description?: string; externalValue?: string; -}; +} -export type OpenAPISchema = { +export interface OpenAPISchema { $ref?: string; type?: string; properties?: { [name: string]: OpenAPISchema }; @@ -133,27 +132,27 @@ export type OpenAPISchema = { minProperties?: number; enum?: any[]; example?: any; -}; +} -export type OpenAPIDiscriminator = { +export interface OpenAPIDiscriminator { propertyName: string; mapping?: { [name: string]: string }; -}; +} -export type OpenAPIMediaType = { +export interface OpenAPIMediaType { schema?: Referenced; example?: any; examples?: { [name: string]: Referenced }; encoding?: { [field: string]: OpenAPIEncoding }; -}; +} -export type OpenAPIEncoding = { +export interface OpenAPIEncoding { contentType: string; headers?: { [name: string]: Referenced }; style: OpenAPIParameterStyle; explode: boolean; allowReserved: boolean; -}; +} export type OpenAPIParameterLocation = 'query' | 'header' | 'path' | 'cookie'; export type OpenAPIParameterStyle = @@ -165,30 +164,34 @@ export type OpenAPIParameterStyle = | 'pipeDelimited' | 'deepObject'; -export type OpenAPIRequestBody = { +export interface OpenAPIRequestBody { description?: string; required?: boolean; content: { [mime: string]: OpenAPIMediaType }; -}; +} -export type OpenAPIResponses = { +export interface OpenAPIResponses { [code: string]: OpenAPIResponse; -}; +} -export type OpenAPIResponse = { +export interface OpenAPIResponse { description?: string; headers?: { [name: string]: Referenced }; content?: { [mime: string]: OpenAPIMediaType }; links?: { [name: string]: Referenced }; -}; +} -export type OpenAPILink = {}; +export interface OpenAPILink { + $ref?: string; +} export type OpenAPIHeader = Omit; -export type OpenAPICallback = {}; +export interface OpenAPICallback { + $ref?: string; +} -export type OpenAPIComponents = { +export interface OpenAPIComponents { schemas?: { [name: string]: Referenced }; responses?: { [name: string]: Referenced }; parameters?: { [name: string]: Referenced }; @@ -198,13 +201,13 @@ export type OpenAPIComponents = { securitySchemes?: { [name: string]: Referenced }; links?: { [name: string]: Referenced }; callbacks?: { [name: string]: Referenced }; -}; +} -export type OpenAPISecurityRequirement = { +export interface OpenAPISecurityRequirement { [name: string]: string[]; -}; +} -export type OpenAPISecurityScheme = { +export interface OpenAPISecurityScheme { type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect'; description?: string; name?: string; @@ -234,27 +237,27 @@ export type OpenAPISecurityScheme = { }; }; openIdConnectUrl?: string; -}; +} -export type OpenAPITag = { +export interface OpenAPITag { name: string; description?: string; externalDocs?: OpenAPIExternalDocumentation; 'x-displayName'?: string; -}; +} -export type OpenAPIExternalDocumentation = { +export interface OpenAPIExternalDocumentation { description?: string; url?: string; -}; +} -export type OpenAPIContact = { +export interface OpenAPIContact { name?: string; url?: string; email?: string; -}; +} -export type OpenAPILicense = { +export interface OpenAPILicense { name: string; url?: string; -}; +} diff --git a/src/utils/JsonPointer.ts b/src/utils/JsonPointer.ts index bad92bb8..96337069 100644 --- a/src/utils/JsonPointer.ts +++ b/src/utils/JsonPointer.ts @@ -17,42 +17,42 @@ export class JsonPointer { * JsonPointerHelper.baseName('/path/foo/subpath', 2) */ static baseName(pointer, level = 1) { - let tokens = JsonPointer.parse(pointer); + const tokens = JsonPointer.parse(pointer); return tokens[tokens.length - level]; } /** - * returns dirname of pointer - * if level > 1 returns corresponding dirname in the hierarchy - * @example - * // returns /path/0 - * JsonPointerHelper.dirName('/path/0/subpath') - * // returns /path - * JsonPointerHelper.dirName('/path/foo/subpath', 2) - */ + * returns dirname of pointer + * if level > 1 returns corresponding dirname in the hierarchy + * @example + * // returns /path/0 + * JsonPointerHelper.dirName('/path/0/subpath') + * // returns /path + * JsonPointerHelper.dirName('/path/foo/subpath', 2) + */ static dirName(pointer, level = 1) { - let tokens = JsonPointer.parse(pointer); + const tokens = JsonPointer.parse(pointer); return JsonPointerLib.compile(tokens.slice(0, tokens.length - level)); } /** - * returns relative path tokens - * @example - * // returns ['subpath'] - * JsonPointerHelper.relative('/path/0', '/path/0/subpath') - * // returns ['foo', 'subpath'] - * JsonPointerHelper.relative('/path', '/path/foo/subpath') - */ + * returns relative path tokens + * @example + * // returns ['subpath'] + * JsonPointerHelper.relative('/path/0', '/path/0/subpath') + * // returns ['foo', 'subpath'] + * JsonPointerHelper.relative('/path', '/path/foo/subpath') + */ static relative(from, to): string[] { - let fromTokens = JsonPointer.parse(from); - let toTokens = JsonPointer.parse(to); + const fromTokens = JsonPointer.parse(from); + const toTokens = JsonPointer.parse(to); return toTokens.slice(fromTokens.length); } /** - * overridden JsonPointer original parse to take care of prefixing '#' symbol - * that is not valid JsonPointer - */ + * overridden JsonPointer original parse to take care of prefixing '#' symbol + * that is not valid JsonPointer + */ static parse(pointer) { let ptr = pointer; if (ptr.charAt(0) === '#') { @@ -70,12 +70,12 @@ export class JsonPointer { */ static join(base, tokens) { // TODO: optimize - let baseTokens = JsonPointer.parse(base); - let resTokens = baseTokens.concat(tokens); + const baseTokens = JsonPointer.parse(base); + const resTokens = baseTokens.concat(tokens); return JsonPointerLib.compile(resTokens); } - static get(object: Object, pointer: string) { + static get(object: object, pointer: string) { return JsonPointerLib.get(object, pointer); } diff --git a/src/utils/dom.ts b/src/utils/dom.ts index fb8c0b2f..dfd7a0b8 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -15,10 +15,10 @@ export function querySelector(selector: string): Element | null { export function html2Str(html: string): string { return html .split(/<[^>]+>/) - .map(function(chunk) { + .map(chunk => { return chunk.trim(); }) - .filter(function(trimmedChunk) { + .filter(trimmedChunk => { return trimmedChunk.length > 0; }) .join(' '); diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 7b4407a2..661b7e82 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -25,7 +25,7 @@ export function mapValues( iteratee: (val: T, key: string, obj: Dict) => P, ): Dict

{ const res: { [key: string]: P } = {}; - for (let key in object) { + for (const key in object) { if (object.hasOwnProperty(key)) { res[key] = iteratee(object[key], key, object); } @@ -35,21 +35,23 @@ export function mapValues( /** * flattens collection using `prop` field as a children - * @param items collection items + * @param collectionItems collection items * @param prop item property with child elements */ -export function flattenByProp(items: T[], prop: P): T[] { +export function flattenByProp( + collectionItems: T[], + prop: P, +): T[] { const res: T[] = []; const iterate = (items: T[]) => { - for (let i = 0; i < items.length; i++) { - const item = items[i]; + for (const item of items) { res.push(item); if (item[prop]) { iterate(item[prop]); } } }; - iterate(items); + iterate(collectionItems); return res; } @@ -64,7 +66,7 @@ export function isAbsolutePath(path: string): boolean { 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); } @@ -92,7 +94,7 @@ export const mergeObjects = (target: T, ...sources: T } if (isMergebleObject(target) && isMergebleObject(source)) { - Object.keys(source).forEach(function(key: string) { + Object.keys(source).forEach((key: string) => { if (isMergebleObject(source[key])) { if (!target[key]) { target[key] = {}; diff --git a/src/utils/highlight.ts b/src/utils/highlight.ts index 1ec8313e..6c5b6ad3 100644 --- a/src/utils/highlight.ts +++ b/src/utils/highlight.ts @@ -1,24 +1,24 @@ import * as Prism from 'prismjs'; import 'prismjs/components/prism-actionscript.js'; +import 'prismjs/components/prism-bash.js'; import 'prismjs/components/prism-c.js'; +import 'prismjs/components/prism-coffeescript.js'; import 'prismjs/components/prism-cpp.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-haskell.js'; import 'prismjs/components/prism-java.js'; import 'prismjs/components/prism-lua.js'; +import 'prismjs/components/prism-markup.js'; // xml import 'prismjs/components/prism-matlab.js'; +import 'prismjs/components/prism-objectivec.js'; import 'prismjs/components/prism-perl.js'; +import 'prismjs/components/prism-php.js'; import 'prismjs/components/prism-python.js'; import 'prismjs/components/prism-r.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-markup.js'; // xml +import 'prismjs/components/prism-swift.js'; import { injectGlobal } from '../styled-components'; diff --git a/src/utils/jsonToHtml.ts b/src/utils/jsonToHtml.ts index 417fa6cf..845543e2 100644 --- a/src/utils/jsonToHtml.ts +++ b/src/utils/jsonToHtml.ts @@ -3,7 +3,7 @@ const COLLAPSE_LEVEL = 2; export function jsonToHTML(json) { level = 1; - var output = ''; + let output = ''; output += '

'; output += valueToHTML(json); output += '
'; @@ -11,7 +11,7 @@ export function jsonToHTML(json) { } function htmlEncode(t) { - return t != undefined + return t !== undefined ? t .toString() .replace(/&/g, '&') @@ -26,9 +26,9 @@ function decorateWithSpan(value, className) { } function valueToHTML(value) { - var valueType = typeof value, - output = ''; - if (value == undefined) { + const valueType = typeof value; + let output = ''; + if (value === undefined || value === null) { output += decorateWithSpan('null', 'type-null'); } else if (value && value.constructor === Array) { level++; @@ -63,12 +63,12 @@ function valueToHTML(value) { } function arrayToHTML(json) { - var collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : ''; - var i, length; - var output = + const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : ''; + let output = '
[
    '; - var hasContents = false; - for (i = 0, length = json.length; i < length; i++) { + let hasContents = false; + const length = json.length; + for (let i = 0; i < length; i++) { hasContents = true; output += '