mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-25 18:13:44 +03:00
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:
parent
7c06735c6d
commit
d3f1c1677c
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(',');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user