Skip to content

Commit

Permalink
Support externalDocs. Closes temando#112
Browse files Browse the repository at this point in the history
  • Loading branch information
Brendan Abbott committed Jul 14, 2017
1 parent 01c384c commit b052d55
Show file tree
Hide file tree
Showing 20 changed files with 159 additions and 57 deletions.
12 changes: 6 additions & 6 deletions docs/open-api-v3-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ This document outlines this project's support for visualising the [Open API V3][
- [ ] [components](#components-object)
- [x] [security](#security-requirement-object)
- [x] [tags](#tag-object)
- [ ] [externalDocs](#external-documentation-object)
- [x] [externalDocs](#external-documentation-object)

### [Info](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#info-object) object

Expand Down Expand Up @@ -104,7 +104,7 @@ This is supported by default as all `$ref` are dereferenced before the definitio
- [x] tags
- [x] summary
- [x] description
- [ ] [externalDocs](#external-documentation-object)
- [x] [externalDocs](#external-documentation-object)
- [ ] operationId
- [x] [parameters](#parameter-object)
- [x] [requestBody](#request-body-object)
Expand All @@ -116,8 +116,8 @@ This is supported by default as all `$ref` are dereferenced before the definitio

### [External Documentation](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#external-documentation-object) object

- [ ] description
- [ ] url
- [x] description
- [x] url

### [Parameter](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#parameter-object) object

Expand Down Expand Up @@ -209,7 +209,7 @@ See [parameter](#parameter-object) object.

- [x] name
- [x] description
- [ ] [externalDocs](#external-documentation-object)
- [x] [externalDocs](#external-documentation-object)

### [Reference](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#reference-object) object

Expand Down Expand Up @@ -263,7 +263,7 @@ The OpenAPI specification also supports several additional properties from JSON
- [ ] readOnly
- [ ] writeOnly
- [ ] [xml](#xml-object)
- [ ] [externalDocs](#external-documentation-object)
- [x] [externalDocs](#external-documentation-object)
- [ ] example
- [ ] deprecated

Expand Down
12 changes: 3 additions & 9 deletions src/components/BodyContent/BodyContent.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ export const styles = createSheet(({ text, backgrounds, sizes }) => ({
'bodyContent': {
display: 'table',
width: '100%',
padding: '10px',
padding: '1rem 0',
boxSizing: 'border-box'
},

'tabs': {
'& > div': {
display: 'inline-block',
padding: '10px 20px',
padding: '1rem 2rem',
cursor: 'pointer',

'&:not($active)': {
Expand All @@ -23,12 +23,6 @@ export const styles = createSheet(({ text, backgrounds, sizes }) => ({

'active': {
backgroundColor: `${backgrounds.schema}`,
borderRadius: '10px 10px 0 0'
},

[`@media (max-width: ${sizes.breakpoint})`]: {
'bodyContent': {
padding: '10px 0'
}
borderRadius: '1rem 1rem 0 0'
}
}))
1 change: 1 addition & 0 deletions src/components/BodySchema/BodySchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export default class BodySchema extends Component {
defaultValue={property.defaultValue}
constraints={property.constraints}
attributes={property.attributes}
docs={property.docs}
onClick={hasSubset ? this.onClick : undefined}
isRequired={property.required}
isOpen={isOpen}
Expand Down
10 changes: 3 additions & 7 deletions src/components/ContentContainer/ContentContainer.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,15 @@ import { createSheet } from '../../theme'

export const styles = createSheet(({ sizes }) => ({
'contentContainer': {
padding: '20px 0',

'& h2': {
paddingLeft: '2rem'
}
padding: '0.5rem 2rem',
margin: '1rem 0'
},

[`@media (max-width: ${sizes.breakpoint})`]: {
'contentContainer': {
padding: '10px 0',
padding: '1rem 0',

'& h2': {
paddingLeft: '1rem',
margin: 0
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/components/Description/Description.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import { createSheet } from '../../theme'

export const styles = createSheet(({ text }) => ({
'description': {
'&:not($inline)': {
color: `${c(text.default).lighten(0.3)}`,
fontSize: '0.9em'
},
color: `${c(text.default).lighten(0.3)}`,
fontSize: '1rem',

'&$inline': {
'&, & p': {
Expand All @@ -17,5 +15,7 @@ export const styles = createSheet(({ text }) => ({
margin: '.5rem 0'
}
},
'inline': {}
'inline': {
paddingRight: '.2rem'
}
}))
27 changes: 27 additions & 0 deletions src/components/Docs/Docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'

import Description from '../Description/Description'
import ExternalLink from '../ExternalLink/ExternalLink'
import { styles } from './Docs.styles'

@styles
export default class Docs extends PureComponent {
render () {
const { url, description, classes } = this.props

return (
<div className={classNames(classes.docs)}>
{description && <Description description={description} />}
<ExternalLink href={url}>More information</ExternalLink>
</div>
)
}
}

Docs.propTypes = {
description: PropTypes.string,
url: PropTypes.string.isRequired,
classes: PropTypes.object
}
7 changes: 7 additions & 0 deletions src/components/Docs/Docs.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createSheet } from '../../theme'

export const styles = createSheet(() => ({
'docs': {
margin: '0.5rem 0'
}
}))
9 changes: 8 additions & 1 deletion src/components/Header/Header.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'

import Docs from '../Docs/Docs'
import Description from '../Description/Description'
import ExternalLink from '../ExternalLink/ExternalLink'
import { styles } from './Header.styles'
Expand Down Expand Up @@ -28,6 +29,8 @@ export default class Header extends PureComponent {
{info && info.termsOfService &&
<ExternalLink href={info.termsOfService}>Terms of Service</ExternalLink>}
</nav>

{info && info.docs && <Docs {...info.docs} />}
</header>
)
}
Expand Down Expand Up @@ -88,7 +91,11 @@ Header.propTypes = {
info: PropTypes.shape({
contact: PropTypes.object,
license: PropTypes.object,
termsOfService: PropTypes.string
termsOfService: PropTypes.string,
docs: PropTypes.shape({
description: PropTypes.string,
url: PropTypes.string.isRequired
})
}),
definitionUrl: PropTypes.string,
classes: PropTypes.object
Expand Down
2 changes: 1 addition & 1 deletion src/components/Header/Header.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createSheet } from '../../theme'

export const styles = createSheet(({ borders, sizes }) => ({
'header': {
padding: '0 20px',
padding: '0 2rem',

'& h1': {
marginBottom: '.5rem'
Expand Down
2 changes: 1 addition & 1 deletion src/components/Method/Method.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const styles = createSheet(({ borders, text, sizes }) => ({
method: {
borderBottom: `1px solid ${borders.default}`,
margin: '0 1rem 2rem 0',
padding: '1rem 2rem',
padding: '1rem 0',

'& > h3': {
marginBottom: '15px',
Expand Down
7 changes: 4 additions & 3 deletions src/components/NavigationTag/NavigationTag.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'

import Indicator from '../Indicator/Indicator'
import NavigationMethod from '../NavigationMethod/NavigationMethod'
import Description from '../Description/Description'
Expand Down Expand Up @@ -89,11 +90,11 @@ export default class NavigationTag extends Component {

NavigationTag.propTypes = {
title: PropTypes.string.isRequired,
hash: PropTypes.string.isRequired,
description: PropTypes.string,
methods: PropTypes.array,
shouldBeExpanded: PropTypes.bool,
onClick: PropTypes.func.isRequired,
hash: PropTypes.string.isRequired,
classes: PropTypes.object,
onClickMethod: PropTypes.func
onClickMethod: PropTypes.func,
classes: PropTypes.object
}
29 changes: 26 additions & 3 deletions src/components/Page/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,17 @@ export default class Page extends Component {
/>
{security && this.renderSecurity(security)}
<ContentContainer>
{services && services.map(
(service) => <ServiceContainer key={service.title} service={service} initialSchemaTreeDepth={initialSchemaTreeDepth} />
)}
{services && services.map((service) => {
const serviceWithDocs = Object.assign({}, service, this.findTagDocs(service.title, navigation))

return (
<ServiceContainer
key={service.title}
service={serviceWithDocs}
initialSchemaTreeDepth={initialSchemaTreeDepth}
/>
)
})}
</ContentContainer>
</div>
</div>
Expand All @@ -68,6 +76,21 @@ export default class Page extends Component {
)
}

findTagDocs (tagHandle, navigation) {
// Find navigation tag that matches given `tagHandle`, and if has docs.
// Note: tag.methods is a way to determine if the navigation has tags at all.
const navigationTag = navigation.find((tag) => (tag.methods && tag.handle === tagHandle && tag.docs))

// No tag, no additional docs.
if (!navigationTag) {
return {}
}

return {
docs: navigationTag.docs
}
}

onToggleNavigation () {
const { isNavOpen } = this.state
if (isNavOpen) {
Expand Down
8 changes: 5 additions & 3 deletions src/components/Property/Property.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { PureComponent } from 'react'
import classNames from 'classnames'
import PropTypes from 'prop-types'

import Docs from '../Docs/Docs'
import Description from '../Description/Description'
import Indicator from '../Indicator/Indicator'
import PropertyConstraints from './PropertyConstraints/PropertyConstraints'
Expand Down Expand Up @@ -47,9 +49,8 @@ export default class Property extends PureComponent {

render () {
const {
type, title, description, constraints, isRequired,
defaultValue, onClick, isOpen, isLast, attributes,
classes
type, title, description, constraints, docs, defaultValue, attributes,
isRequired, isOpen, isLast, onClick, classes
} = this.props

const {name, isEnumTrimmed} = this.state
Expand Down Expand Up @@ -104,6 +105,7 @@ export default class Property extends PureComponent {
{enumValues && this.renderEnumValues(enumValues, isEnumTrimmed)}
{defaultValue !== undefined && this.renderDefaultValue(defaultValue)}
{description && <div><Description isInline description={description} /></div>}
{docs && <Docs {...docs} />}
</div>
}
</td>
Expand Down
8 changes: 1 addition & 7 deletions src/components/SecurityContainer/SecurityContainer.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createSheet } from '../../theme'

export const styles = createSheet(({ backgrounds, borders, sizes }) => ({
'securityContainer': {
padding: '1rem 2rem',
padding: '1rem 0',
borderBottom: `1px solid ${borders.default}`

},
Expand All @@ -26,11 +26,5 @@ export const styles = createSheet(({ backgrounds, borders, sizes }) => ({
'& > li > span': {
fontWeight: 600
}
},

[`@media (max-width: ${sizes.breakpoint})`]: {
'securityContainer': {
padding: '1rem'
}
}
}))
5 changes: 4 additions & 1 deletion src/components/ServiceContainer/ServiceContainer.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'

import Docs from '../Docs/Docs'
import Method from '../Method/Method'
import { styles } from './ServiceContainer.styles'

@styles
export default class ServiceContainer extends PureComponent {
render () {
const { service, classes, initialSchemaTreeDepth } = this.props
const { title, methods } = service
const { title, docs, methods } = service

return (
<div className={classes.serviceContainer} id={title}>
<h2>{title}</h2>
{docs && <Docs {...docs} />}
{methods.map(
(method) => <Method key={method.link} method={method} initialSchemaTreeDepth={initialSchemaTreeDepth} />
)}
Expand Down
4 changes: 4 additions & 0 deletions src/parser/open-api/schemaParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ function getPropertyNode (nodeName, propertyNode, required = false) {
outputNode.defaultValue = propertyNode.default
}

if (propertyNode.externalDocs) {
outputNode.docs = propertyNode.externalDocs
}

if (propertyNode.additionalProperties === false) {
outputNode.additionalProperties = false
}
Expand Down
4 changes: 4 additions & 0 deletions src/parser/open-api/v3/navigationParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export function getServicesMethod ({ path, method, request, params, responses })
servicesMethod.description = method.description
}

if (method.externalDocs) {
servicesMethod.docs = method.externalDocs
}

if (params) {
servicesMethod.parameters = params
}
Expand Down
Loading

0 comments on commit b052d55

Please sign in to comment.