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 50const nonLinkableTypes = ['Date', 'Uint8Array']; 51 52export const resolveTypeName = ({ 53 elementType, 54 name, 55 type, 56 types, 57 typeArguments, 58}: TypeDefinitionData): string | JSX.Element => { 59 if (name) { 60 if (type === 'reference') { 61 if (typeArguments) { 62 if (name === 'Promise') { 63 return ( 64 <span> 65 {'Promise<'} 66 {typeArguments.map(resolveTypeName)} 67 {'>'} 68 </span> 69 ); 70 } else { 71 return `${typeArguments.map(resolveTypeName)}`; 72 } 73 } else { 74 if (nonLinkableTypes.includes(name)) { 75 return name; 76 } else { 77 return ( 78 <InternalLink href={`#${name.toLowerCase()}`} key={`type-link-${name}`}> 79 {name} 80 </InternalLink> 81 ); 82 } 83 } 84 } else { 85 return name; 86 } 87 } else if (elementType?.name) { 88 if (type === 'array') { 89 return elementType.name + '[]'; 90 } 91 return elementType.name + type; 92 } else if (type === 'union' && types?.length) { 93 return types.map((t: TypeDefinitionTypesData) => `${t.name || t.value}`).join(' | '); 94 } 95 return 'undefined'; 96}; 97 98export const renderParam = ({ comment, name, type }: MethodParamData): JSX.Element => ( 99 <LI key={`param-${name}`}> 100 <B> 101 {name} (<InlineCode>{resolveTypeName(type)}</InlineCode>) 102 </B> 103 <CommentTextBlock comment={comment} renderers={inlineRenderers} withDash /> 104 </LI> 105); 106 107type CommentTextBlockProps = { 108 comment?: CommentData; 109 renderers?: React.ComponentProps<typeof ReactMarkdown>['renderers']; 110 withDash?: boolean; 111}; 112 113export const CommentTextBlock: React.FC<CommentTextBlockProps> = ({ 114 comment, 115 renderers, 116 withDash, 117}) => { 118 const shortText = comment?.shortText?.trim().length ? ( 119 <ReactMarkdown renderers={renderers}>{comment.shortText}</ReactMarkdown> 120 ) : null; 121 const text = comment?.text?.trim().length ? ( 122 <ReactMarkdown renderers={renderers}>{comment.text}</ReactMarkdown> 123 ) : null; 124 return ( 125 <> 126 {withDash && (shortText || text) ? ' - ' : null} 127 {shortText} 128 {text} 129 </> 130 ); 131}; 132