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