1import React from 'react'; 2import ReactMarkdown from 'react-markdown'; 3 4import { Code, InlineCode } from '~/components/base/code'; 5import { H4 } from '~/components/base/headings'; 6import { InternalLink } from '~/components/base/link'; 7import { LI, UL } from '~/components/base/list'; 8import { B, P, Quote } from '~/components/base/paragraph'; 9import { 10 CommentData, 11 MethodParamData, 12 TypeDefinitionData, 13 TypeDefinitionTypesData, 14} from '~/components/plugins/api/APIDataTypes'; 15 16export enum TypeDocKind { 17 Enum = 4, 18 Variable = 32, 19 Function = 64, 20 Class = 128, 21 Interface = 256, 22 Property = 1024, 23 TypeAlias = 4194304, 24} 25 26export const renderers: React.ComponentProps<typeof ReactMarkdown>['renderers'] = { 27 blockquote: ({ children }) => ( 28 <Quote> 29 {React.Children.map(children, child => 30 child.type.name === 'paragraph' ? child.props.children : child 31 )} 32 </Quote> 33 ), 34 code: ({ value, language }) => <Code className={`language-${language}`}>{value}</Code>, 35 heading: ({ children }) => <H4>{children}</H4>, 36 inlineCode: ({ value }) => <InlineCode>{value}</InlineCode>, 37 list: ({ children }) => <UL>{children}</UL>, 38 listItem: ({ children }) => <LI>{children}</LI>, 39 link: ({ href, children }) => <InternalLink href={href}>{children}</InternalLink>, 40 paragraph: ({ children }) => (children ? <P>{children}</P> : null), 41 strong: ({ children }) => <B>{children}</B>, 42 text: ({ value }) => (value ? <span>{value}</span> : null), 43}; 44 45export const inlineRenderers: React.ComponentProps<typeof ReactMarkdown>['renderers'] = { 46 ...renderers, 47 paragraph: ({ children }) => (children ? <span>{children}</span> : null), 48}; 49 50export const resolveTypeName = ({ 51 elementType, 52 name, 53 type, 54 types, 55 typeArguments, 56}: TypeDefinitionData): string | JSX.Element => { 57 if (name) { 58 if (type === 'reference') { 59 if (typeArguments) { 60 if (name === 'Promise') { 61 return ( 62 <span> 63 {'Promise<'} 64 {typeArguments.map(resolveTypeName)} 65 {'>'} 66 </span> 67 ); 68 } else { 69 return `${typeArguments.map(resolveTypeName)}`; 70 } 71 } else { 72 if (name === 'Date') { 73 return name; 74 } else { 75 return ( 76 <InternalLink href={`#${name.toLowerCase()}`} key={`type-link-${name}`}> 77 {name} 78 </InternalLink> 79 ); 80 } 81 } 82 } else { 83 return name; 84 } 85 } else if (elementType?.name) { 86 if (type === 'array') { 87 return elementType.name + '[]'; 88 } 89 return elementType.name + type; 90 } else if (type === 'union' && types?.length) { 91 return types.map((t: TypeDefinitionTypesData) => `${t.name || t.value}`).join(' | '); 92 } 93 return 'undefined'; 94}; 95 96export const renderParam = ({ comment, name, type }: MethodParamData): JSX.Element => ( 97 <LI key={`param-${name}`}> 98 <B> 99 {name} (<InlineCode>{resolveTypeName(type)}</InlineCode>) 100 </B> 101 <CommentTextBlock comment={comment} renderers={inlineRenderers} withDash /> 102 </LI> 103); 104 105type CommentTextBlockProps = { 106 comment?: CommentData; 107 renderers?: React.ComponentProps<typeof ReactMarkdown>['renderers']; 108 withDash?: boolean; 109}; 110 111export const CommentTextBlock: React.FC<CommentTextBlockProps> = ({ 112 comment, 113 renderers, 114 withDash, 115}) => { 116 const shortText = comment?.shortText?.trim().length ? ( 117 <ReactMarkdown renderers={renderers}>{comment.shortText}</ReactMarkdown> 118 ) : null; 119 const text = comment?.text?.trim().length ? ( 120 <ReactMarkdown renderers={renderers}>{comment.text}</ReactMarkdown> 121 ) : null; 122 return ( 123 <> 124 {withDash && (shortText || text) ? ' - ' : null} 125 {shortText} 126 {text} 127 </> 128 ); 129}; 130