Skip to content

Commit cb106cc

Browse files
committed
feat: display xml examples if present in response examples
1 parent d2c790f commit cb106cc

File tree

9 files changed

+121
-28
lines changed

9 files changed

+121
-28
lines changed

demo/swagger.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ paths:
617617
type: string
618618
examples:
619619
application/json: OK
620+
application/xml: <message> OK </message>
620621
headers:
621622
X-Rate-Limit:
622623
type: integer

lib/components/RequestSamples/request-samples.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ header {
6464
}
6565

6666
:host /deep/ tabs ul {
67-
padding-top: 10px;
67+
padding-top: 10px;
6868
}
6969

7070
.code-sample pre {

lib/components/ResponsesSamples/responses-samples.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import { Component, Input, OnInit, ChangeDetectionStrategy } from '@angular/core';
44
import { BaseComponent, SpecManager } from '../base';
55
import JsonPointer from '../../utils/JsonPointer';
6-
import { statusCodeType, getJsonLike } from '../../utils/helpers';
6+
import { statusCodeType, getJsonLikeSample } from '../../utils/helpers';
77

88

99
function isNumeric(n) {
1010
return (!isNaN(parseFloat(n)) && isFinite(n));
1111
}
1212

1313
function hasExample(response) {
14-
return ((response.examples && getJsonLike(response.examples)) ||
14+
return ((response.examples && getJsonLikeSample(response.examples)) ||
1515
response.schema);
1616
}
1717

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
1-
<div class="snippet">
2-
<!-- in case sample is not available for some reason -->
3-
<pre *ngIf="sample == undefined"> Sample unavailable </pre>
4-
<div class="action-buttons">
5-
<span copy-button [copyText]="sample" class="hint--top-left hint--inversed"> <a>Copy</a> </span>
6-
<span> <a *ngIf="enableButtons" (click)="expandAll()">Expand all</a> </span>
7-
<span> <a *ngIf="enableButtons" (click)="collapseAll()">Collapse all</a> </span>
1+
<ng-template #jsonSnippet>
2+
<div class="snippet">
3+
<!-- in case sample is not available for some reason -->
4+
<pre *ngIf="sample == undefined"> Sample unavailable </pre>
5+
<div class="action-buttons">
6+
<span copy-button [copyText]="sample" class="hint--top-left hint--inversed"> <a>Copy</a> </span>
7+
<span> <a *ngIf="enableButtons" (click)="expandAll()">Expand all</a> </span>
8+
<span> <a *ngIf="enableButtons" (click)="collapseAll()">Collapse all</a> </span>
9+
</div>
10+
<pre [innerHtml]="sample | jsonFormatter"></pre>
811
</div>
9-
<pre [innerHtml]="sample | jsonFormatter"></pre>
10-
</div>
12+
</ng-template>
13+
14+
<tabs *ngIf="xmlSample; else jsonSnippet">
15+
<tab tabTitle="JSON">
16+
<ng-container *ngTemplateOutlet="jsonSnippet"></ng-container>
17+
</tab>
18+
<tab tabTitle="XML" *ngIf="xmlSample">
19+
<div class="snippet">
20+
<div class="action-buttons">
21+
<span copy-button [copyText]="xmlSample" class="hint--top-left hint--inversed"> <a>Copy</a> </span>
22+
</div>
23+
<pre class="xml-sample" [innerHtml]="xmlSample | prism:'xml'"></pre>
24+
</div>
25+
</tab>
26+
</tabs>

lib/components/SchemaSample/schema-sample.scss

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,34 @@
44
display: block;
55
}
66

7+
8+
/* tabs */
9+
10+
:host /deep/ tabs {
11+
margin-top: 1em;
12+
> ul {
13+
margin: 0;
14+
padding: 0;
15+
16+
> li {
17+
padding: 2px 10px;
18+
display: inline-block;
19+
background: #131a1d;
20+
border-bottom: 1px solid trasparent;
21+
color: $sample-panel-headers-color;
22+
23+
&.active {
24+
color: white;
25+
border-bottom: 1px solid $sample-panel-headers-color;
26+
}
27+
}
28+
}
29+
30+
.action-buttons {
31+
margin-top: -2em;
32+
}
33+
}
34+
735
pre {
836
background-color: transparent;
937
padding: 0;
@@ -99,7 +127,7 @@ pre {
99127
padding-left: 6px;
100128
}
101129

102-
.redoc-json {
130+
.redoc-json, .xml-sample {
103131
overflow-x: auto;
104132
padding: 20px;
105133
border-radius: $border-radius*2;

lib/components/SchemaSample/schema-sample.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as OpenAPISampler from 'openapi-sampler';
66
import JsonPointer from '../../utils/JsonPointer';
77
import { BaseComponent, SpecManager } from '../base';
88
import { SchemaNormalizer } from '../../services/schema-normalizer.service';
9-
import { getJsonLike } from '../../utils/helpers';
9+
import { getJsonLikeSample, getXmlLikeSample} from '../../utils/helpers';
1010

1111
@Component({
1212
selector: 'schema-sample',
@@ -20,6 +20,7 @@ export class SchemaSample extends BaseComponent implements OnInit {
2020

2121
element: any;
2222
sample: any;
23+
xmlSample: string;
2324
enableButtons: boolean = false;
2425

2526
private _normalizer:SchemaNormalizer;
@@ -34,7 +35,7 @@ export class SchemaSample extends BaseComponent implements OnInit {
3435
this.bindEvents();
3536

3637
let base:any = this.componentSchema;
37-
let sample;
38+
let sample, xmlSample;
3839

3940
// got pointer not directly to the schema but e.g. to the response obj
4041
if (this.componentSchema.schema) {
@@ -50,7 +51,12 @@ export class SchemaSample extends BaseComponent implements OnInit {
5051
base.examples = requestExamples;
5152
}
5253

53-
let jsonLikeSample = base.examples && getJsonLike(base.examples);
54+
let xmlLikeSample = base.examples && getXmlLikeSample(base.examples);
55+
if (xmlLikeSample) {
56+
this.xmlSample = xmlLikeSample;
57+
}
58+
59+
let jsonLikeSample = base.examples && getJsonLikeSample(base.examples);
5460
if (jsonLikeSample) {
5561
sample = jsonLikeSample;
5662
} else {

lib/utils/helpers.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,26 @@ export function isJsonLike(contentType: string): boolean {
123123
return contentType.search(/json/i) !== -1;
124124
}
125125

126-
export function getJsonLike(object: Object) {
127-
const jsonLikeKeys = Object.keys(object).filter(isJsonLike);
126+
export function isXmlLike(contentType: string): boolean {
127+
return contentType.search(/xml/i) !== -1;
128+
}
129+
130+
export function getJsonLikeSample(samples: Object) {
131+
const jsonLikeKeys = Object.keys(samples).filter(isJsonLike);
128132

129133
if (!jsonLikeKeys.length) {
130134
return false;
131135
}
132136

133-
return object[jsonLikeKeys.shift()];
137+
return samples[jsonLikeKeys[0]];
138+
}
139+
140+
export function getXmlLikeSample(samples: Object) {
141+
const xmlLikeKeys = Object.keys(samples).filter(isXmlLike);
142+
143+
if (!xmlLikeKeys.length) {
144+
return false;
145+
}
146+
147+
return samples[xmlLikeKeys[0]];
134148
}

lib/vendor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import 'prismjs/components/prism-bash.js';
1818
import 'prismjs/components/prism-swift.js';
1919
import 'prismjs/components/prism-objectivec.js';
2020
import 'prismjs/components/prism-scala.js';
21+
import 'prismjs/components/prism-markup.js'; // xml
2122

2223
import 'dropkickjs/build/css/dropkick.css';
2324
import 'prismjs/themes/prism-dark.css';

tests/unit/helpers.spec.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
'use strict';
22

3-
import {statusCodeType, isJsonLike, getJsonLike } from '../../lib/utils/helpers';
3+
import {
4+
statusCodeType,
5+
isJsonLike,
6+
getJsonLikeSample,
7+
isXmlLike,
8+
getXmlLikeSample
9+
} from '../../lib/utils/helpers';
410

511
describe('Utils', () => {
612
describe('statusCodeType', () => {
@@ -41,24 +47,45 @@ describe('Utils', () => {
4147
});
4248
});
4349

44-
describe('getJsonLike', () => {
50+
describe('getJsonLikeSample', () => {
4551
it('Should return a value when a JSON-like key exists', () => {
4652
const examples = {
47-
"application/vnd.api+json": {
48-
"message": "Hello World"
53+
'application/vnd.api+json': {
54+
'message': 'Hello World'
4955
},
50-
"application/xml": "<message>Hello World</message>"
56+
'application/xml': '<message>Hello World</message>'
5157
};
5258

53-
(getJsonLike(examples).message).should.be.equal("Hello World");
59+
(getJsonLikeSample(examples).message).should.be.equal('Hello World');
5460
});
5561

5662
it('Should return undefined when no JSON-like key exists', () => {
5763
const examples = {
58-
"application/xml": "<message>Hello World</message>"
64+
'application/xml': '<message>Hello World</message>'
5965
};
6066

61-
getJsonLike(examples).should.be.equal(false);
67+
getJsonLikeSample(examples).should.be.equal(false);
6268
});
63-
})
69+
});
70+
71+
describe('getXmlLikeSample', () => {
72+
it('Should return a value when a XML-like key exists', () => {
73+
const examples = {
74+
'application/vnd.api+json': {
75+
'message': 'Hello World'
76+
},
77+
'application/vnd.api+xml': '<message>Hello World</message>'
78+
};
79+
80+
(getXmlLikeSample(examples)).should.be.equal('<message>Hello World</message>');
81+
});
82+
83+
it('Should return undefined when no XML-like key exists', () => {
84+
const examples = {
85+
'application/json': '<message>Hello World</message>'
86+
};
87+
88+
getXmlLikeSample(examples).should.be.equal(false);
89+
});
90+
});
6491
});

0 commit comments

Comments
 (0)