1import ReactMarkdown from 'react-markdown'; 2 3import { HeadingType } from '~/common/headingManager'; 4import { mdComponentsNoValidation } from '~/components/plugins/api/APISectionUtils'; 5import { Cell, HeaderCell, Row, Table, TableHead } from '~/ui/components/Table'; 6import { P, CODE, createPermalinkedComponent } from '~/ui/components/Text'; 7 8export type Property = { 9 description?: string[]; 10 name: string; 11 type?: string | string[]; 12 enum?: string[]; 13 properties?: Property[]; 14}; 15 16type FormattedProperty = { 17 name: string; 18 description: string; 19 nestingLevel: number; 20}; 21 22type Props = { 23 schema: Property[]; 24}; 25 26const Anchor = createPermalinkedComponent(P, { 27 baseNestingLevel: 4, 28 sidebarType: HeadingType.InlineCode, 29}); 30 31const PropertyName = ({ name, nestingLevel }: Pick<FormattedProperty, 'name' | 'nestingLevel'>) => ( 32 <Anchor level={nestingLevel}> 33 <CODE>{name}</CODE> 34 </Anchor> 35); 36 37export function formatSchema(rawSchema: Property[]) { 38 const formattedSchema: FormattedProperty[] = []; 39 40 rawSchema.map(property => { 41 appendProperty(formattedSchema, property, 0); 42 }); 43 44 return formattedSchema; 45} 46 47//appends a property and recursively appends sub-properties 48function appendProperty( 49 formattedSchema: FormattedProperty[], 50 property: Property, 51 _nestingLevel: number 52) { 53 let nestingLevel = _nestingLevel; 54 55 formattedSchema.push({ 56 name: property.name, 57 description: createDescription(property), 58 nestingLevel, 59 }); 60 61 nestingLevel++; 62 63 if (property.properties) { 64 (property.properties ?? []).forEach(subproperty => { 65 appendProperty(formattedSchema, subproperty, nestingLevel); 66 }); 67 } 68} 69 70export function _getType(property: Property) { 71 if (property.enum) { 72 return `enum: ${property.enum.join(', ')}`; 73 } else { 74 return property.type?.toString().replace(/,/g, ' || '); 75 } 76} 77 78export function createDescription(property: Property) { 79 let propertyDescription = `**(${_getType(property)})**`; 80 if (property.description) { 81 propertyDescription += ` - ` + property.description.join('\n'); 82 } 83 84 return propertyDescription; 85} 86 87export const EasJsonPropertiesTable = ({ schema }: Props) => { 88 const formattedSchema = formatSchema(schema); 89 90 return ( 91 <Table> 92 <TableHead> 93 <Row> 94 <HeaderCell>Property</HeaderCell> 95 <HeaderCell>Description</HeaderCell> 96 </Row> 97 </TableHead> 98 <tbody> 99 {formattedSchema.map((property, index) => ( 100 <Row key={index}> 101 <Cell fitContent> 102 <div 103 data-testid={property.name} 104 style={{ 105 marginLeft: `${property.nestingLevel * 32}px`, 106 display: property.nestingLevel ? 'list-item' : 'block', 107 listStyleType: property.nestingLevel % 2 ? 'default' : 'circle', 108 overflowX: 'visible', 109 }}> 110 <PropertyName name={property.name} nestingLevel={property.nestingLevel} /> 111 </div> 112 </Cell> 113 <Cell> 114 <ReactMarkdown components={mdComponentsNoValidation}> 115 {property.description} 116 </ReactMarkdown> 117 </Cell> 118 </Row> 119 ))} 120 </tbody> 121 </Table> 122 ); 123}; 124