Skip to content

Commit 6ae2693

Browse files
fabsrctim-lai
andauthored
feat: Render external docs links and descriptions (#7559)
Co-authored-by: Tim Lai <[email protected]>
1 parent 7dd167b commit 6ae2693

File tree

10 files changed

+443
-14
lines changed

10 files changed

+443
-14
lines changed

src/core/components/array-model.jsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { Component } from "react"
22
import PropTypes from "prop-types"
33
import ImPropTypes from "react-immutable-proptypes"
4+
import { sanitizeUrl } from "core/utils"
45

56
const propClass = "property"
67

@@ -25,12 +26,16 @@ export default class ArrayModel extends Component {
2526
let description = schema.get("description")
2627
let items = schema.get("items")
2728
let title = schema.get("title") || displayName || name
28-
let properties = schema.filter( ( v, key) => ["type", "items", "description", "$$ref"].indexOf(key) === -1 )
29+
let properties = schema.filter( ( v, key) => ["type", "items", "description", "$$ref", "externalDocs"].indexOf(key) === -1 )
30+
let externalDocsUrl = schema.getIn(["externalDocs", "url"])
31+
let externalDocsDescription = schema.getIn(["externalDocs", "description"])
32+
2933

3034
const Markdown = getComponent("Markdown", true)
3135
const ModelCollapse = getComponent("ModelCollapse")
3236
const Model = getComponent("Model")
3337
const Property = getComponent("Property")
38+
const Link = getComponent("Link")
3439

3540
const titleEl = title &&
3641
<span className="model-title">
@@ -52,6 +57,11 @@ export default class ArrayModel extends Component {
5257
!description ? (properties.size ? <div className="markdown"></div> : null) :
5358
<Markdown source={ description } />
5459
}
60+
{ externalDocsUrl &&
61+
<div className="external-docs">
62+
<Link target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</Link>
63+
</div>
64+
}
5565
<span>
5666
<Model
5767
{ ...this.props }

src/core/components/object-model.jsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component, } from "react"
22
import PropTypes from "prop-types"
33
import { List } from "immutable"
44
import ImPropTypes from "react-immutable-proptypes"
5+
import { sanitizeUrl } from "core/utils"
56

67
const braceOpen = "{"
78
const braceClose = "}"
@@ -44,12 +45,15 @@ export default class ObjectModel extends Component {
4445
let infoProperties = schema
4546
.filter( ( v, key) => ["maxProperties", "minProperties", "nullable", "example"].indexOf(key) !== -1 )
4647
let deprecated = schema.get("deprecated")
48+
let externalDocsUrl = schema.getIn(["externalDocs", "url"])
49+
let externalDocsDescription = schema.getIn(["externalDocs", "description"])
4750

4851
const JumpToPath = getComponent("JumpToPath", true)
4952
const Markdown = getComponent("Markdown", true)
5053
const Model = getComponent("Model")
5154
const ModelCollapse = getComponent("ModelCollapse")
5255
const Property = getComponent("Property")
56+
const Link = getComponent("Link")
5357

5458
const JumpToPathSection = () => {
5559
return <span className="model-jump-to-path"><JumpToPath specPath={specPath} /></span>
@@ -93,6 +97,17 @@ export default class ObjectModel extends Component {
9397
</td>
9498
</tr>
9599
}
100+
{
101+
externalDocsUrl &&
102+
<tr className={"external-docs"}>
103+
<td>
104+
externalDocs:
105+
</td>
106+
<td>
107+
<Link target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</Link>
108+
</td>
109+
</tr>
110+
}
96111
{
97112
!deprecated ? null :
98113
<tr className={"property"}>
@@ -103,7 +118,6 @@ export default class ObjectModel extends Component {
103118
true
104119
</td>
105120
</tr>
106-
107121
}
108122
{
109123
!(properties && properties.size) ? null : properties.entrySeq().filter(

src/core/components/operation-tag.jsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,14 @@ export default class OperationTag extends React.Component {
8888
</small>
8989
}
9090

91-
{!tagExternalDocsDescription ? null :
91+
{!tagExternalDocsUrl ? null :
9292
<div className="info__externaldocs">
9393
<small>
94-
{tagExternalDocsDescription}
95-
{tagExternalDocsUrl ? ": " : null}
96-
{tagExternalDocsUrl ?
97-
<Link
94+
<Link
9895
href={sanitizeUrl(tagExternalDocsUrl)}
9996
onClick={(e) => e.stopPropagation()}
10097
target="_blank"
101-
>{tagExternalDocsUrl}</Link> : null
102-
}
98+
>{tagExternalDocsDescription || tagExternalDocsUrl}</Link>
10399
</small>
104100
</div>
105101
}

src/core/components/operation.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,11 @@ export default class Operation extends PureComponent {
133133
<div className="opblock-external-docs-wrapper">
134134
<h4 className="opblock-title_normal">Find more details</h4>
135135
<div className="opblock-external-docs">
136-
<span className="opblock-external-docs__description">
137-
<Markdown source={ externalDocs.description } />
138-
</span>
136+
{externalDocs.description &&
137+
<span className="opblock-external-docs__description">
138+
<Markdown source={ externalDocs.description } />
139+
</span>
140+
}
139141
<Link target="_blank" className="opblock-external-docs__link" href={sanitizeUrl(externalDocsUrl)}>{externalDocsUrl}</Link>
140142
</div>
141143
</div> : null

src/core/components/primitive-model.jsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { Component } from "react"
22
import PropTypes from "prop-types"
3-
import { getExtensions } from "core/utils"
3+
import { getExtensions, sanitizeUrl } from "core/utils"
44

55
const propClass = "property primitive"
66

@@ -33,12 +33,17 @@ export default class Primitive extends Component {
3333
let description = schema.get("description")
3434
let extensions = getExtensions(schema)
3535
let properties = schema
36-
.filter((_, key) => ["enum", "type", "format", "description", "$$ref"].indexOf(key) === -1)
36+
.filter((_, key) => ["enum", "type", "format", "description", "$$ref", "externalDocs"].indexOf(key) === -1)
3737
.filterNot((_, key) => extensions.has(key))
38+
let externalDocsUrl = schema.getIn(["externalDocs", "url"])
39+
let externalDocsDescription = schema.getIn(["externalDocs", "description"])
40+
3841
const Markdown = getComponent("Markdown", true)
3942
const EnumModel = getComponent("EnumModel")
4043
const Property = getComponent("Property")
4144
const ModelCollapse = getComponent("ModelCollapse")
45+
const Link = getComponent("Link")
46+
4247
const titleEl = title &&
4348
<span className="model-title">
4449
<span className="model-title__text">{title}</span>
@@ -60,6 +65,12 @@ export default class Primitive extends Component {
6065
!description ? null :
6166
<Markdown source={description} />
6267
}
68+
{
69+
externalDocsUrl &&
70+
<div className="external-docs">
71+
<Link target="_blank" href={sanitizeUrl(externalDocsUrl)}>{externalDocsDescription || externalDocsUrl}</Link>
72+
</div>
73+
}
6374
{
6475
xml && xml.size ? (<span><br /><span className={propClass}>xml:</span>
6576
{

src/style/_layout.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@
118118
flex: 1;
119119
}
120120
}
121+
122+
.info__externaldocs
123+
{
124+
text-align: right;
125+
}
121126
}
122127

123128
.parameter__type

src/style/_models.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@
108108
color: #6b6b6b;
109109
}
110110
}
111+
112+
.external-docs
113+
{
114+
color: #666;
115+
font-weight: normal;
116+
}
111117
}
112118

113119
table.model
@@ -157,6 +163,19 @@ table.model
157163
vertical-align: top;
158164
}
159165
}
166+
167+
&.external-docs
168+
{
169+
td:first-child
170+
{
171+
font-weight: bold;
172+
}
173+
}
174+
175+
.renderedMarkdown p:first-child
176+
{
177+
margin-top: 0;
178+
}
160179
}
161180
}
162181

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
openapi: 3.0.2
2+
3+
info:
4+
title: External Docs
5+
version: "1"
6+
7+
externalDocs:
8+
description: Read external docs
9+
url: http://swagger.io
10+
11+
tags:
12+
- name: pet
13+
description: Everything about your Pets
14+
externalDocs:
15+
description: Pet Documentation
16+
url: http://swagger.io
17+
- name: petWithoutDescription
18+
externalDocs:
19+
url: http://swagger.io
20+
21+
paths:
22+
/pet:
23+
put:
24+
externalDocs:
25+
description: More details about putting a pet
26+
url: http://swagger.io
27+
tags:
28+
- pet
29+
summary: Update an existing pet
30+
description: Update an existing pet by Id
31+
operationId: updatePet
32+
requestBody:
33+
description: Update an existent pet in the store
34+
content:
35+
application/json:
36+
schema:
37+
$ref: '#/components/schemas/Pet'
38+
required: true
39+
responses:
40+
"200":
41+
description: Successful operation
42+
content:
43+
application/json:
44+
schema:
45+
$ref: '#/components/schemas/Pet'
46+
"400":
47+
description: Invalid ID supplied
48+
"404":
49+
description: Pet not found
50+
"405":
51+
description: Validation exception
52+
post:
53+
externalDocs:
54+
url: http://swagger.io
55+
tags:
56+
- pet
57+
summary: Add a new pet to the store
58+
description: Add a new pet to the store
59+
operationId: addPet
60+
requestBody:
61+
description: Create a new pet in the store
62+
content:
63+
application/json:
64+
schema:
65+
$ref: '#/components/schemas/Pet'
66+
required: true
67+
responses:
68+
"200":
69+
description: Successful operation
70+
content:
71+
application/json:
72+
schema:
73+
$ref: '#/components/schemas/Pet'
74+
"405":
75+
description: Invalid input
76+
77+
components:
78+
schemas:
79+
Pet:
80+
required:
81+
- name
82+
- photoUrls
83+
type: object
84+
description: This is a Pet
85+
externalDocs:
86+
description: More Docs About Pet
87+
url: http://swagger.io
88+
deprecated: true
89+
properties:
90+
id:
91+
type: integer
92+
format: int64
93+
example: 10
94+
name:
95+
type: string
96+
example: doggie
97+
photoUrls:
98+
type: array
99+
items:
100+
type: string
101+
status:
102+
type: string
103+
description: pet status in the store
104+
enum:
105+
- available
106+
- pending
107+
- sold
108+
Object:
109+
type: object
110+
externalDocs:
111+
description: Object Docs
112+
url: http://swagger.io
113+
properties:
114+
name:
115+
type: string
116+
ObjectWithoutDescription:
117+
type: object
118+
externalDocs:
119+
url: http://swagger.io
120+
properties:
121+
name:
122+
type: string
123+
Primitive:
124+
description: Just a string schema
125+
type: string
126+
externalDocs:
127+
description: Primitive Docs
128+
url: http://swagger.io
129+
PrimitiveWithoutDescription:
130+
description: Just a string schema
131+
type: string
132+
externalDocs:
133+
url: http://swagger.io
134+
Array:
135+
description: Just an array schema
136+
type: array
137+
externalDocs:
138+
description: Array Docs
139+
url: http://swagger.io
140+
items:
141+
type: string
142+
ArrayWithoutDescription:
143+
description: Just an array schema
144+
type: array
145+
externalDocs:
146+
url: http://swagger.io
147+
items:
148+
type: string

0 commit comments

Comments
 (0)