import { Anchor, Box, Code, Text } from '@mantine/core'; import { DocNodeKind, StandardTags } from '@microsoft/tsdoc'; import Link from 'next/link'; import { Fragment, ReactNode } from 'react'; import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter'; import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'; import { BlockComment } from './BlockComment'; import type { DocBlockJSON } from '~/DocModel/comment/CommentBlock'; import type { AnyDocNodeJSON } from '~/DocModel/comment/CommentNode'; import type { DocNodeContainerJSON } from '~/DocModel/comment/CommentNodeContainer'; import type { DocFencedCodeJSON } from '~/DocModel/comment/FencedCodeCommentNode'; import type { DocLinkTagJSON } from '~/DocModel/comment/LinkTagCommentNode'; import type { DocPlainTextJSON } from '~/DocModel/comment/PlainTextCommentNode'; import type { DocCommentJSON } from '~/DocModel/comment/RootComment'; export function TSDoc({ node }: { node: AnyDocNodeJSON }): JSX.Element { let numberOfExamples = 0; let exampleIndex = 0; const createNode = (node: AnyDocNodeJSON, idx?: number): ReactNode => { switch (node.kind) { case DocNodeKind.PlainText: return ( {(node as DocPlainTextJSON).text} ); case DocNodeKind.Paragraph: return ( {(node as DocNodeContainerJSON).nodes.map((node, idx) => createNode(node, idx))} ); case DocNodeKind.SoftBreak: return ; case DocNodeKind.LinkTag: { const { codeDestination, urlDestination, text } = node as DocLinkTagJSON; if (codeDestination) { return ( {text ?? codeDestination.name} ); } if (urlDestination) { return ( {text ?? urlDestination} ); } return null; } case DocNodeKind.CodeSpan: { const { code } = node as DocFencedCodeJSON; return ( {code} ); } case DocNodeKind.FencedCode: { const { language, code } = node as DocFencedCodeJSON; return ( {code} ); } case DocNodeKind.ParamBlock: case DocNodeKind.Block: { const { tag } = node as DocBlockJSON; if (tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase) { exampleIndex++; } const index = numberOfExamples > 1 ? exampleIndex : undefined; return ( {(node as DocBlockJSON).content.map((node, idx) => createNode(node, idx))} ); } case DocNodeKind.Comment: { const comment = node as DocCommentJSON; // Cheat a bit by finding out how many comments we have beforehand... numberOfExamples = comment.customBlocks.filter( (block) => block.tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase, ).length; return {comment.customBlocks.map((node, idx) => createNode(node, idx))}; } default: console.log(`Captured unknown node kind: ${node.kind}`); break; } return null; }; return ( {node.kind === 'Paragraph' || node.kind === 'Section' ? ( <>{(node as DocNodeContainerJSON).nodes.map((node, idx) => createNode(node, idx))} ) : ( createNode(node) )} ); }