Skip to content

Commit

Permalink
feat: add sampleCollapseLevel option (#937)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
alex-karo authored and RomanHotsiy committed Jul 29, 2019
1 parent 7c06735 commit d3f1c16
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 18 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 13 additions & 6 deletions src/components/JsonViewer/JsonViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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>
);

Expand Down
15 changes: 15 additions & 0 deletions src/services/RedocNormalizedOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface RedocRawOptions {
onlyRequiredInSamples?: boolean | string;
showExtensions?: boolean | string | string[];
hideSingleRequestSampleTab?: boolean | string;
jsonSampleExpandLevel?: number | string | 'all';

unstable_ignoreMimeParameters?: boolean;

Expand Down Expand Up @@ -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;
Expand All @@ -126,6 +137,7 @@ export class RedocNormalizedOptions {
onlyRequiredInSamples: boolean;
showExtensions: boolean | string[];
hideSingleRequestSampleTab: boolean;
jsonSampleExpandLevel: number;
enumSkipQuotes: boolean;

/* tslint:disable-next-line */
Expand Down Expand Up @@ -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);
Expand Down
23 changes: 11 additions & 12 deletions src/utils/jsonToHtml.ts
Original file line number Diff line number Diff line change
@@ -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;
}
Expand Down Expand Up @@ -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');
Expand All @@ -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">`;
Expand All @@ -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 += ',';
}
Expand All @@ -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(
Expand All @@ -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(',');
}
Expand Down

0 comments on commit d3f1c16

Please sign in to comment.