feat: add sampleCollapseLevel option (#937)

* feat: add sampleCollapseLevel option

* fix: rename sampleCollapseLevel option to jsonSampleExpandLevel
Change README.md description

* fix: provide maxCollapseLevel option via argument

* fix: rename normalizer function and some vars
This commit is contained in:
Aleksandr Karo 2019-07-29 15:26:16 +03:00 committed by Roman Hotsiy
parent 7c06735c6d
commit d3f1c1677c
4 changed files with 40 additions and 18 deletions

View File

@ -243,6 +243,7 @@ You can use all of the following options with standalone version on <redoc> tag
* `hideDownloadButton` - do not show "Download" spec button. **THIS DOESN'T MAKE YOUR SPEC PRIVATE**, it just hides the button.
* `disableSearch` - disable search indexing and search box
* `onlyRequiredInSamples` - shows only required fields in request samples.
* `jsonSampleExpandLevel` - set the default expand level for JSON payload samples (responses and request body). Special value 'all' expands all levels. The default value is `2`.
* `theme` - ReDoc theme. Not documented yet. For details check source code: [theme.ts](https://github.com/Redocly/redoc/blob/master/src/theme.ts)
## Advanced usage of standalone version

View File

@ -5,6 +5,7 @@ import { SampleControls } from '../../common-elements';
import { CopyButtonWrapper } from '../../common-elements/CopyButtonWrapper';
import { PrismDiv } from '../../common-elements/PrismDiv';
import { jsonToHTML } from '../../utils/jsonToHtml';
import { OptionsContext } from '../OptionsProvider';
import { jsonStyles } from './style';
export interface JsonProps {
@ -32,12 +33,18 @@ class Json extends React.PureComponent<JsonProps> {
<span onClick={this.expandAll}> Expand all </span>
<span onClick={this.collapseAll}> Collapse all </span>
</SampleControls>
<PrismDiv
className={this.props.className}
// tslint:disable-next-line
ref={node => (this.node = node!)}
dangerouslySetInnerHTML={{ __html: jsonToHTML(this.props.data) }}
/>
<OptionsContext.Consumer>
{options => (
<PrismDiv
className={this.props.className}
// tslint:disable-next-line
ref={node => (this.node = node!)}
dangerouslySetInnerHTML={{
__html: jsonToHTML(this.props.data, options.jsonSampleExpandLevel),
}}
/>
)}
</OptionsContext.Consumer>
</JsonViewerWrap>
);

View File

@ -22,6 +22,7 @@ export interface RedocRawOptions {
onlyRequiredInSamples?: boolean | string;
showExtensions?: boolean | string | string[];
hideSingleRequestSampleTab?: boolean | string;
jsonSampleExpandLevel?: number | string | 'all';
unstable_ignoreMimeParameters?: boolean;
@ -111,6 +112,16 @@ export class RedocNormalizedOptions {
return value;
}
private static normalizeJsonSampleExpandLevel(level?: number | string | 'all'): number {
if (level === 'all') {
return +Infinity;
}
if (!isNaN(Number(level))) {
return Math.ceil(Number(level));
}
return 2;
}
theme: ResolvedThemeInterface;
scrollYOffset: () => number;
hideHostname: boolean;
@ -126,6 +137,7 @@ export class RedocNormalizedOptions {
onlyRequiredInSamples: boolean;
showExtensions: boolean | string[];
hideSingleRequestSampleTab: boolean;
jsonSampleExpandLevel: number;
enumSkipQuotes: boolean;
/* tslint:disable-next-line */
@ -158,6 +170,9 @@ export class RedocNormalizedOptions {
this.onlyRequiredInSamples = argValueToBoolean(raw.onlyRequiredInSamples);
this.showExtensions = RedocNormalizedOptions.normalizeShowExtensions(raw.showExtensions);
this.hideSingleRequestSampleTab = argValueToBoolean(raw.hideSingleRequestSampleTab);
this.jsonSampleExpandLevel = RedocNormalizedOptions.normalizeJsonSampleExpandLevel(
raw.jsonSampleExpandLevel,
);
this.enumSkipQuotes = argValueToBoolean(raw.enumSkipQuotes);
this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters);

View File

@ -1,11 +1,10 @@
let level = 1;
const COLLAPSE_LEVEL = 2;
export function jsonToHTML(json) {
export function jsonToHTML(json, maxExpandLevel) {
level = 1;
let output = '';
output += '<div class="redoc-json">';
output += valueToHTML(json);
output += valueToHTML(json, maxExpandLevel);
output += '</div>';
return output;
}
@ -33,20 +32,20 @@ function punctuation(val) {
return '<span class="token punctuation">' + val + '</span>';
}
function valueToHTML(value) {
function valueToHTML(value, maxExpandLevel: number) {
const valueType = typeof value;
let output = '';
if (value === undefined || value === null) {
output += decorateWithSpan('null', 'token keyword');
} else if (value && value.constructor === Array) {
level++;
output += arrayToHTML(value);
output += arrayToHTML(value, maxExpandLevel);
level--;
} else if (value && value.constructor === Date) {
output += decorateWithSpan('"' + value.toISOString() + '"', 'token string');
} else if (valueType === 'object') {
level++;
output += objectToHTML(value);
output += objectToHTML(value, maxExpandLevel);
level--;
} else if (valueType === 'number') {
output += decorateWithSpan(value, 'token number');
@ -70,8 +69,8 @@ function valueToHTML(value) {
return output;
}
function arrayToHTML(json) {
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
function arrayToHTML(json, maxExpandLevel: number) {
const collapsed = level > maxExpandLevel ? 'collapsed' : '';
let output = `<div class="collapser"></div>${punctuation(
'[',
)}<span class="ellipsis"></span><ul class="array collapsible">`;
@ -80,7 +79,7 @@ function arrayToHTML(json) {
for (let i = 0; i < length; i++) {
hasContents = true;
output += '<li><div class="hoverable ' + collapsed + '">';
output += valueToHTML(json[i]);
output += valueToHTML(json[i], maxExpandLevel);
if (i < length - 1) {
output += ',';
}
@ -93,8 +92,8 @@ function arrayToHTML(json) {
return output;
}
function objectToHTML(json) {
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
function objectToHTML(json, maxExpandLevel: number) {
const collapsed = level > maxExpandLevel ? 'collapsed' : '';
const keys = Object.keys(json);
const length = keys.length;
let output = `<div class="collapser"></div>${punctuation(
@ -106,7 +105,7 @@ function objectToHTML(json) {
hasContents = true;
output += '<li><div class="hoverable ' + collapsed + '">';
output += '<span class="property token string">"' + htmlEncode(key) + '"</span>: ';
output += valueToHTML(json[key]);
output += valueToHTML(json[key], maxExpandLevel);
if (i < length - 1) {
output += punctuation(',');
}