feat: add support hidePropertiesPrefix

This commit is contained in:
Alex Varchuk 2025-01-21 11:56:37 +01:00
parent 349a194879
commit 93d6b6c431
No known key found for this signature in database
GPG Key ID: 8A9260AE529FF454
7 changed files with 50 additions and 7 deletions

View File

@ -19,6 +19,8 @@ import { Schema } from '../Schema/Schema';
import type { SchemaOptions } from '../Schema/Schema'; import type { SchemaOptions } from '../Schema/Schema';
import type { FieldModel } from '../../services/models'; import type { FieldModel } from '../../services/models';
import { OptionsContext } from '../OptionsProvider';
import { RedocNormalizedOptions } from '../../services/RedocNormalizedOptions';
export interface FieldProps extends SchemaOptions { export interface FieldProps extends SchemaOptions {
className?: string; className?: string;
@ -27,12 +29,15 @@ export interface FieldProps extends SchemaOptions {
field: FieldModel; field: FieldModel;
expandByDefault?: boolean; expandByDefault?: boolean;
fieldParentsName?: string[];
renderDiscriminatorSwitch?: (opts: FieldProps) => JSX.Element; renderDiscriminatorSwitch?: (opts: FieldProps) => JSX.Element;
} }
@observer @observer
export class Field extends React.Component<FieldProps> { export class Field extends React.Component<FieldProps> {
static contextType = OptionsContext;
context: RedocNormalizedOptions;
toggle = () => { toggle = () => {
if (this.props.field.expanded === undefined && this.props.expandByDefault) { if (this.props.field.expanded === undefined && this.props.expandByDefault) {
this.props.field.collapse(); this.props.field.collapse();
@ -49,12 +54,12 @@ export class Field extends React.Component<FieldProps> {
}; };
render() { render() {
const { className = '', field, isLast, expandByDefault } = this.props; const { hidePropertiesPrefix } = this.context;
const { className = '', field, isLast, expandByDefault, fieldParentsName = [] } = this.props;
const { name, deprecated, required, kind } = field; const { name, deprecated, required, kind } = field;
const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular; const withSubSchema = !field.schema.isPrimitive && !field.schema.isCircular;
const expanded = field.expanded === undefined ? expandByDefault : field.expanded; const expanded = field.expanded === undefined ? expandByDefault : field.expanded;
const labels = ( const labels = (
<> <>
{kind === 'additionalProperties' && <PropertyLabel>additional property</PropertyLabel>} {kind === 'additionalProperties' && <PropertyLabel>additional property</PropertyLabel>}
@ -75,6 +80,10 @@ export class Field extends React.Component<FieldProps> {
onKeyPress={this.handleKeyPress} onKeyPress={this.handleKeyPress}
aria-label={`expand ${name}`} aria-label={`expand ${name}`}
> >
{!hidePropertiesPrefix &&
fieldParentsName.map(
name => name + '.\u200B', // zero-width space, a special character is used for correct line breaking
)}
<span className="property-name">{name}</span> <span className="property-name">{name}</span>
<ShelfIcon direction={expanded ? 'down' : 'right'} /> <ShelfIcon direction={expanded ? 'down' : 'right'} />
</button> </button>
@ -83,6 +92,10 @@ export class Field extends React.Component<FieldProps> {
) : ( ) : (
<PropertyNameCell className={deprecated ? 'deprecated' : undefined} kind={kind} title={name}> <PropertyNameCell className={deprecated ? 'deprecated' : undefined} kind={kind} title={name}>
<PropertyBullet /> <PropertyBullet />
{!hidePropertiesPrefix &&
fieldParentsName.map(
name => name + '.\u200B', // zero-width space, a special character is used for correct line breaking
)}
<span className="property-name">{name}</span> <span className="property-name">{name}</span>
{labels} {labels}
</PropertyNameCell> </PropertyNameCell>
@ -102,6 +115,7 @@ export class Field extends React.Component<FieldProps> {
<InnerPropertiesWrap> <InnerPropertiesWrap>
<Schema <Schema
schema={field.schema} schema={field.schema}
fieldParentsName={[...(fieldParentsName || []), field.name]}
skipReadOnly={this.props.skipReadOnly} skipReadOnly={this.props.skipReadOnly}
skipWriteOnly={this.props.skipWriteOnly} skipWriteOnly={this.props.skipWriteOnly}
showTitle={this.props.showTitle} showTitle={this.props.showTitle}

View File

@ -16,14 +16,24 @@ export class ArraySchema extends React.PureComponent<SchemaProps> {
render() { render() {
const schema = this.props.schema; const schema = this.props.schema;
const itemsSchema = schema.items; const itemsSchema = schema.items;
const fieldParentsName = this.props.fieldParentsName;
const minMaxItems = const minMaxItems =
schema.minItems === undefined && schema.maxItems === undefined schema.minItems === undefined && schema.maxItems === undefined
? '' ? ''
: `(${humanizeConstraints(schema)})`; : `(${humanizeConstraints(schema)})`;
const updatedParentsArray = fieldParentsName
? [...fieldParentsName.slice(0, -1), fieldParentsName[fieldParentsName.length - 1] + '[]']
: fieldParentsName;
if (schema.fields) { if (schema.fields) {
return <ObjectSchema {...(this.props as any)} level={this.props.level} />; return (
<ObjectSchema
{...(this.props as any)}
level={this.props.level}
fieldParentsName={updatedParentsArray}
/>
);
} }
if (schema.displayType && !itemsSchema && !minMaxItems.length) { if (schema.displayType && !itemsSchema && !minMaxItems.length) {
return ( return (
@ -37,7 +47,7 @@ export class ArraySchema extends React.PureComponent<SchemaProps> {
<div> <div>
<ArrayOpenningLabel> Array {minMaxItems}</ArrayOpenningLabel> <ArrayOpenningLabel> Array {minMaxItems}</ArrayOpenningLabel>
<PaddedSchema> <PaddedSchema>
<Schema {...this.props} schema={itemsSchema} /> <Schema {...this.props} schema={itemsSchema} fieldParentsName={updatedParentsArray} />
</PaddedSchema> </PaddedSchema>
<ArrayClosingLabel /> <ArrayClosingLabel />
</div> </div>

View File

@ -16,6 +16,7 @@ export interface ObjectSchemaProps extends SchemaProps {
fieldName: string; fieldName: string;
parentSchema: SchemaModel; parentSchema: SchemaModel;
}; };
fieldParentsName?: string[];
} }
export const ObjectSchema = observer( export const ObjectSchema = observer(
@ -26,6 +27,7 @@ export const ObjectSchema = observer(
skipReadOnly, skipReadOnly,
skipWriteOnly, skipWriteOnly,
level, level,
fieldParentsName,
}: ObjectSchemaProps) => { }: ObjectSchemaProps) => {
const { expandSingleSchemaField, showObjectSchemaExamples, schemasExpansionLevel } = const { expandSingleSchemaField, showObjectSchemaExamples, schemasExpansionLevel } =
React.useContext(OptionsContext); React.useContext(OptionsContext);
@ -58,6 +60,7 @@ export const ObjectSchema = observer(
isLast={isLast} isLast={isLast}
field={field} field={field}
expandByDefault={expandByDefault} expandByDefault={expandByDefault}
fieldParentsName={Number(level) > 1 ? fieldParentsName : []}
renderDiscriminatorSwitch={ renderDiscriminatorSwitch={
discriminator?.fieldName === field.name discriminator?.fieldName === field.name
? () => ( ? () => (

View File

@ -21,6 +21,7 @@ export interface SchemaOptions {
export interface SchemaProps extends SchemaOptions { export interface SchemaProps extends SchemaOptions {
schema: SchemaModel; schema: SchemaModel;
fieldParentsName?: string[];
} }
@observer @observer

View File

@ -88,6 +88,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -363,6 +364,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -625,6 +627,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -949,6 +952,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -1236,6 +1240,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -1494,6 +1499,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -1777,6 +1783,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -2090,6 +2097,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -2365,6 +2373,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -2627,6 +2636,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
"hideDownloadButtons": false, "hideDownloadButtons": false,
"hideFab": false, "hideFab": false,
"hideHostname": false, "hideHostname": false,
"hidePropertiesPrefix": true,
"hideRequestPayloadSample": false, "hideRequestPayloadSample": false,
"hideSchemaPattern": false, "hideSchemaPattern": false,
"hideSchemaTitles": false, "hideSchemaTitles": false,
@ -2955,6 +2965,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
}, },
} }
} }
fieldParentsName={[]}
isLast={false} isLast={false}
key="packSize" key="packSize"
showExamples={false} showExamples={false}
@ -3029,6 +3040,7 @@ exports[`Components SchemaView discriminator should correctly render discriminat
}, },
} }
} }
fieldParentsName={[]}
isLast={true} isLast={true}
key="type" key="type"
renderDiscriminatorSwitch={[Function]} renderDiscriminatorSwitch={[Function]}

View File

@ -24,7 +24,7 @@ export class MenuBuilder {
const hasAutogenerated = [...(spec.tags || [])].find( const hasAutogenerated = [...(spec.tags || [])].find(
tag => tag?.name === schemaDefinitionsTagName, tag => tag?.name === schemaDefinitionsTagName,
); );
console.log('hasAutogenerated', hasAutogenerated, schemaDefinitionsTagName);
if (!hasAutogenerated && schemaDefinitionsTagName) { if (!hasAutogenerated && schemaDefinitionsTagName) {
tags.push({ name: schemaDefinitionsTagName }); tags.push({ name: schemaDefinitionsTagName });
} }
@ -38,7 +38,7 @@ export class MenuBuilder {
} else { } else {
items.push(...MenuBuilder.getTagsItems(parser, tagsMap, undefined, undefined, options)); items.push(...MenuBuilder.getTagsItems(parser, tagsMap, undefined, undefined, options));
} }
console.log('items', items);
return items; return items;
} }

View File

@ -70,6 +70,7 @@ export interface RedocRawOptions {
hideFab?: boolean; hideFab?: boolean;
minCharacterLengthToInitSearch?: number; minCharacterLengthToInitSearch?: number;
showWebhookVerb?: boolean; showWebhookVerb?: boolean;
hidePropertiesPrefix?: boolean;
} }
export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean { export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
@ -273,6 +274,7 @@ export class RedocNormalizedOptions {
hideFab: boolean; hideFab: boolean;
minCharacterLengthToInitSearch: number; minCharacterLengthToInitSearch: number;
showWebhookVerb: boolean; showWebhookVerb: boolean;
hidePropertiesPrefix?: boolean;
nonce?: string; nonce?: string;
@ -358,5 +360,6 @@ export class RedocNormalizedOptions {
this.hideFab = argValueToBoolean(raw.hideFab); this.hideFab = argValueToBoolean(raw.hideFab);
this.minCharacterLengthToInitSearch = argValueToNumber(raw.minCharacterLengthToInitSearch) || 3; this.minCharacterLengthToInitSearch = argValueToNumber(raw.minCharacterLengthToInitSearch) || 3;
this.showWebhookVerb = argValueToBoolean(raw.showWebhookVerb); this.showWebhookVerb = argValueToBoolean(raw.showWebhookVerb);
this.hidePropertiesPrefix = argValueToBoolean(raw.hidePropertiesPrefix, true);
} }
} }