mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-11 09:03:29 +01:00
refactor(website): extract layouts and use more server components (#9027)
Closes https://github.com/discordjs/discord.js/issues/8920 Closes https://github.com/discordjs/discord.js/issues/8997
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import { Alert } from '@discordjs/ui';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
|
||||
export function Block({ children, title }: PropsWithChildren<{ title: string }>) {
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<h5 className="font-bold">{title}</h5>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ExampleBlock({
|
||||
children,
|
||||
exampleIndex,
|
||||
}: PropsWithChildren<{ exampleIndex?: number | undefined }>): JSX.Element {
|
||||
return <Block title={`Example ${exampleIndex ? exampleIndex : ''}`}>{children}</Block>;
|
||||
}
|
||||
|
||||
export function DefaultValueBlock({ children }: PropsWithChildren): JSX.Element {
|
||||
return <Block title="Default value">{children}</Block>;
|
||||
}
|
||||
|
||||
export function RemarksBlock({ children }: PropsWithChildren): JSX.Element {
|
||||
return <Block title="Remarks">{children}</Block>;
|
||||
}
|
||||
|
||||
export function DeprecatedBlock({ children }: PropsWithChildren): JSX.Element {
|
||||
return (
|
||||
<Alert title="Deprecated" type="danger">
|
||||
{children}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
export function SeeBlock({ children }: PropsWithChildren): JSX.Element {
|
||||
return <Block title="See Also">{children}</Block>;
|
||||
}
|
||||
121
apps/website/src/components/documentation/tsdoc/TSDoc.tsx
Normal file
121
apps/website/src/components/documentation/tsdoc/TSDoc.tsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import type { ApiItem } from '@microsoft/api-extractor-model';
|
||||
import type { DocComment, DocFencedCode, DocLinkTag, DocNode, DocNodeContainer, DocPlainText } from '@microsoft/tsdoc';
|
||||
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
|
||||
import Link from 'next/link';
|
||||
import { Fragment, useCallback, type ReactNode } from 'react';
|
||||
import { SyntaxHighlighter } from '../../SyntaxHighlighter';
|
||||
import { resolveItemURI } from '../util';
|
||||
import { DeprecatedBlock, ExampleBlock, RemarksBlock, SeeBlock } from './BlockComment';
|
||||
import { ItemLink } from '~/components/ItemLink';
|
||||
|
||||
export function TSDoc({ item, tsdoc }: { item: ApiItem; tsdoc: DocNode }): JSX.Element {
|
||||
const createNode = useCallback(
|
||||
(tsdoc: DocNode, idx?: number): ReactNode => {
|
||||
switch (tsdoc.kind) {
|
||||
case DocNodeKind.PlainText:
|
||||
return (
|
||||
<span className="break-words" key={idx}>
|
||||
{(tsdoc as DocPlainText).text}
|
||||
</span>
|
||||
);
|
||||
case DocNodeKind.Section:
|
||||
case DocNodeKind.Paragraph:
|
||||
return (
|
||||
<span className="break-words leading-relaxed" key={idx}>
|
||||
{(tsdoc as DocNodeContainer).nodes.map((node, idx) => createNode(node, idx))}
|
||||
</span>
|
||||
);
|
||||
case DocNodeKind.SoftBreak:
|
||||
return <Fragment key={idx} />;
|
||||
case DocNodeKind.LinkTag: {
|
||||
const { codeDestination, urlDestination, linkText } = tsdoc as DocLinkTag;
|
||||
|
||||
if (codeDestination) {
|
||||
const foundItem = item
|
||||
.getAssociatedModel()
|
||||
?.resolveDeclarationReference(codeDestination, item).resolvedApiItem;
|
||||
|
||||
if (!foundItem) return null;
|
||||
|
||||
return (
|
||||
<ItemLink
|
||||
className="text-blurple focus:ring-width-2 focus:ring-blurple rounded font-mono outline-0 focus:ring"
|
||||
itemURI={resolveItemURI(foundItem)}
|
||||
key={idx}
|
||||
>
|
||||
{linkText ?? foundItem.displayName}
|
||||
</ItemLink>
|
||||
);
|
||||
}
|
||||
|
||||
if (urlDestination) {
|
||||
return (
|
||||
<Link
|
||||
className="text-blurple focus:ring-width-2 focus:ring-blurple rounded font-mono outline-0 focus:ring"
|
||||
href={urlDestination}
|
||||
key={idx}
|
||||
>
|
||||
{linkText ?? urlDestination}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
case DocNodeKind.CodeSpan: {
|
||||
const { code } = tsdoc as DocFencedCode;
|
||||
return (
|
||||
<code className="font-mono text-sm" key={idx}>
|
||||
{code}
|
||||
</code>
|
||||
);
|
||||
}
|
||||
|
||||
case DocNodeKind.FencedCode: {
|
||||
const { language, code } = tsdoc as DocFencedCode;
|
||||
return <SyntaxHighlighter code={code} key={idx} language={language} />;
|
||||
}
|
||||
|
||||
case DocNodeKind.Comment: {
|
||||
const comment = tsdoc as DocComment;
|
||||
|
||||
const exampleBlocks = comment.customBlocks.filter(
|
||||
(block) => block.blockTag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-2">
|
||||
{comment.deprecatedBlock ? (
|
||||
<DeprecatedBlock>{createNode(comment.deprecatedBlock.content)}</DeprecatedBlock>
|
||||
) : null}
|
||||
{comment.summarySection ? createNode(comment.summarySection) : null}
|
||||
{comment.remarksBlock ? <RemarksBlock>{createNode(comment.remarksBlock.content)}</RemarksBlock> : null}
|
||||
{exampleBlocks.length
|
||||
? exampleBlocks.map((block, idx) => <ExampleBlock key={idx}>{createNode(block.content)}</ExampleBlock>)
|
||||
: null}
|
||||
{comment.seeBlocks.length ? (
|
||||
<SeeBlock>{comment.seeBlocks.map((seeBlock, idx) => createNode(seeBlock.content, idx))}</SeeBlock>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
default:
|
||||
// console.log(`Captured unknown node kind: ${node.kind}`);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
[item],
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{tsdoc.kind === 'Paragraph' || tsdoc.kind === 'Section' ? (
|
||||
<>{(tsdoc as DocNodeContainer).nodes.map((node, idx) => createNode(node, idx))}</>
|
||||
) : (
|
||||
createNode(tsdoc)
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user