mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
feat(website): render tsdoc examples (#8494)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { ApiEnum, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { CommentNodeContainer } from './comment/CommentNodeContainer';
|
||||
import { nodeContainer } from './comment/CommentNodeContainer';
|
||||
import { genToken, TokenDocumentation } from '~/util/parse.server';
|
||||
|
||||
export interface EnumMemberData {
|
||||
@@ -18,9 +18,7 @@ export class DocEnum extends DocItem<ApiEnum> {
|
||||
this.members = item.members.map((member) => ({
|
||||
name: member.name,
|
||||
initializerTokens: member.initializerExcerpt?.spannedTokens.map((token) => genToken(this.model, token)) ?? [],
|
||||
summary: member.tsdocComment
|
||||
? new CommentNodeContainer(member.tsdocComment.summarySection, model, member).toJSON()
|
||||
: null,
|
||||
summary: member.tsdocComment ? nodeContainer(member.tsdocComment.summarySection, model, member) : null,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { ApiModel, ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
||||
import { CommentNodeContainer } from './comment/CommentNodeContainer';
|
||||
import { createCommentNode } from './comment';
|
||||
import type { AnyDocNodeJSON } from './comment/CommentNode';
|
||||
import type { DocNodeContainerJSON } from './comment/CommentNodeContainer';
|
||||
import type { ReferenceData } from '~/util/model.server';
|
||||
import { resolveName, genReference, TokenDocumentation, genToken } from '~/util/parse.server';
|
||||
|
||||
@@ -13,9 +15,10 @@ export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
||||
public readonly excerpt: string;
|
||||
public readonly excerptTokens: TokenDocumentation[] = [];
|
||||
public readonly kind: string;
|
||||
public readonly remarks: CommentNodeContainer | null;
|
||||
public readonly summary: CommentNodeContainer | null;
|
||||
public readonly remarks: DocNodeContainerJSON | null;
|
||||
public readonly summary: DocNodeContainerJSON | null;
|
||||
public readonly containerKey: string;
|
||||
public readonly comment: AnyDocNodeJSON | null;
|
||||
|
||||
public constructor(model: ApiModel, item: T) {
|
||||
this.item = item;
|
||||
@@ -26,12 +29,13 @@ export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
||||
this.excerpt = item.excerpt.text;
|
||||
this.excerptTokens = item.excerpt.spannedTokens.map((token) => genToken(model, token));
|
||||
this.remarks = item.tsdocComment?.remarksBlock
|
||||
? new CommentNodeContainer(item.tsdocComment.remarksBlock.content, model, item.parent)
|
||||
? (createCommentNode(item.tsdocComment.remarksBlock, model, item.parent) as DocNodeContainerJSON)
|
||||
: null;
|
||||
this.summary = item.tsdocComment?.summarySection
|
||||
? new CommentNodeContainer(item.tsdocComment.summarySection, model, item.parent)
|
||||
? (createCommentNode(item.tsdocComment.summarySection, model, item.parent) as DocNodeContainerJSON)
|
||||
: null;
|
||||
this.containerKey = item.containerKey;
|
||||
this.comment = item.tsdocComment ? createCommentNode(item.tsdocComment, model, item.parent) : null;
|
||||
}
|
||||
|
||||
public get path() {
|
||||
@@ -54,13 +58,14 @@ export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
||||
return {
|
||||
name: this.name,
|
||||
referenceData: this.referenceData,
|
||||
summary: this.summary?.toJSON() ?? null,
|
||||
summary: this.summary,
|
||||
excerpt: this.excerpt,
|
||||
excerptTokens: this.excerptTokens,
|
||||
kind: this.kind,
|
||||
remarks: this.remarks?.toJSON() ?? null,
|
||||
remarks: this.remarks,
|
||||
path: this.path,
|
||||
containerKey: this.containerKey,
|
||||
comment: this.comment,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
18
packages/website/src/DocModel/comment/CommentBlock.ts
Normal file
18
packages/website/src/DocModel/comment/CommentBlock.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { ApiModel, ApiItem } from '@microsoft/api-extractor-model';
|
||||
import type { DocBlock } from '@microsoft/tsdoc';
|
||||
import { createCommentNode } from '.';
|
||||
import { blockTag, DocBlockTagJSON } from './CommentBlockTag';
|
||||
import { AnyDocNodeJSON, DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export interface DocBlockJSON extends DocNodeJSON {
|
||||
content: AnyDocNodeJSON[];
|
||||
tag: DocBlockTagJSON;
|
||||
}
|
||||
|
||||
export function block(block: DocBlock, model: ApiModel, parentItem?: ApiItem) {
|
||||
return {
|
||||
...node(block),
|
||||
content: block.content.nodes.map((node) => createCommentNode(node, model, parentItem)),
|
||||
tag: blockTag(block.blockTag),
|
||||
};
|
||||
}
|
||||
13
packages/website/src/DocModel/comment/CommentBlockTag.ts
Normal file
13
packages/website/src/DocModel/comment/CommentBlockTag.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { DocBlockTag } from '@microsoft/tsdoc';
|
||||
import { type DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export interface DocBlockTagJSON extends DocNodeJSON {
|
||||
tagName: string;
|
||||
}
|
||||
|
||||
export function blockTag(blockTag: DocBlockTag): DocBlockTagJSON {
|
||||
return {
|
||||
...node(blockTag),
|
||||
tagName: blockTag.tagName,
|
||||
};
|
||||
}
|
||||
13
packages/website/src/DocModel/comment/CommentCodeSpan.ts
Normal file
13
packages/website/src/DocModel/comment/CommentCodeSpan.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { DocCodeSpan } from '@microsoft/tsdoc';
|
||||
import { DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export interface DocCodeSpanJSON extends DocNodeJSON {
|
||||
code: string;
|
||||
}
|
||||
|
||||
export function codeSpan(codeSpan: DocCodeSpan): DocCodeSpanJSON {
|
||||
return {
|
||||
...node(codeSpan),
|
||||
code: codeSpan.code,
|
||||
};
|
||||
}
|
||||
@@ -1,22 +1,28 @@
|
||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import type { DocNode } from '@microsoft/tsdoc';
|
||||
import type { DocNode, DocNodeKind } from '@microsoft/tsdoc';
|
||||
import type { DocBlockJSON } from './CommentBlock';
|
||||
import type { DocCodeSpanJSON } from './CommentCodeSpan';
|
||||
import type { DocNodeContainerJSON } from './CommentNodeContainer';
|
||||
import type { DocFencedCodeJSON } from './FencedCodeCommentNode';
|
||||
import type { DocLinkTagJSON } from './LinkTagCommentNode';
|
||||
import type { DocPlainTextJSON } from './PlainTextCommentNode';
|
||||
import type { DocCommentJSON } from './RootComment';
|
||||
|
||||
export class CommentNode<T extends DocNode = DocNode> {
|
||||
public readonly node: T;
|
||||
public readonly kind: string;
|
||||
public readonly model: ApiModel;
|
||||
public readonly parentItem: ApiItem | null;
|
||||
|
||||
public constructor(node: T, model: ApiModel, parentItem?: ApiItem) {
|
||||
this.node = node;
|
||||
this.kind = node.kind;
|
||||
this.model = model;
|
||||
this.parentItem = parentItem ?? null;
|
||||
}
|
||||
|
||||
public toJSON() {
|
||||
return {
|
||||
kind: this.kind,
|
||||
};
|
||||
}
|
||||
export interface DocNodeJSON {
|
||||
kind: DocNodeKind;
|
||||
}
|
||||
|
||||
export type AnyDocNodeJSON =
|
||||
| DocNodeJSON
|
||||
| DocPlainTextJSON
|
||||
| DocNodeContainerJSON
|
||||
| DocLinkTagJSON
|
||||
| DocFencedCodeJSON
|
||||
| DocBlockJSON
|
||||
| DocCommentJSON
|
||||
| DocCodeSpanJSON;
|
||||
|
||||
export function node(node: DocNode): DocNodeJSON {
|
||||
return {
|
||||
kind: node.kind as DocNodeKind,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import type { DocNodeContainer } from '@microsoft/tsdoc';
|
||||
import { createCommentNode } from '.';
|
||||
import { CommentNode } from './CommentNode';
|
||||
import { AnyDocNodeJSON, DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export class CommentNodeContainer<T extends DocNodeContainer = DocNodeContainer> extends CommentNode<DocNodeContainer> {
|
||||
public readonly nodes: CommentNode[];
|
||||
|
||||
public constructor(container: T, model: ApiModel, parentItem?: ApiItem) {
|
||||
super(container, model, parentItem);
|
||||
this.nodes = container.nodes.map((node) => createCommentNode(node, model, parentItem));
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
nodes: this.nodes.map((node) => node.toJSON()),
|
||||
};
|
||||
}
|
||||
export interface DocNodeContainerJSON extends DocNodeJSON {
|
||||
nodes: AnyDocNodeJSON[];
|
||||
}
|
||||
|
||||
export function nodeContainer(
|
||||
container: DocNodeContainer,
|
||||
model: ApiModel,
|
||||
parentItem?: ApiItem,
|
||||
): DocNodeContainerJSON {
|
||||
return {
|
||||
...node(container),
|
||||
nodes: container.nodes.map((node) => createCommentNode(node, model, parentItem)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
import type { ApiModel, ApiItem } from '@microsoft/api-extractor-model';
|
||||
import type { DocFencedCode } from '@microsoft/tsdoc';
|
||||
import { CommentNode } from './CommentNode';
|
||||
import { DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export class FencedCodeCommentNode extends CommentNode<DocFencedCode> {
|
||||
public readonly code: string;
|
||||
public readonly language: string;
|
||||
|
||||
public constructor(node: DocFencedCode, model: ApiModel, parentItem?: ApiItem) {
|
||||
super(node, model, parentItem);
|
||||
this.code = node.code;
|
||||
this.language = node.language;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
code: this.code,
|
||||
language: this.language,
|
||||
};
|
||||
}
|
||||
export interface DocFencedCodeJSON extends DocNodeJSON {
|
||||
code: string;
|
||||
language: string;
|
||||
}
|
||||
|
||||
export function fencedCode(fencedCode: DocFencedCode) {
|
||||
return {
|
||||
...node(fencedCode),
|
||||
language: fencedCode.language,
|
||||
code: fencedCode.code,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import type { DocDeclarationReference, DocLinkTag } from '@microsoft/tsdoc';
|
||||
import { CommentNode } from './CommentNode';
|
||||
import { DocNodeJSON, node } from './CommentNode';
|
||||
import { generatePath, resolveName } from '~/util/parse.server';
|
||||
|
||||
export interface DocLinkTagJSON extends DocNodeJSON {
|
||||
text: string | null;
|
||||
codeDestination: LinkTagCodeLink | null;
|
||||
urlDestination: string | null;
|
||||
}
|
||||
|
||||
export function genToken(
|
||||
model: ApiModel,
|
||||
ref: DocDeclarationReference,
|
||||
@@ -31,24 +37,16 @@ export interface LinkTagCodeLink {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export class LinkTagCommentNode extends CommentNode<DocLinkTag> {
|
||||
public readonly codeDestination: LinkTagCodeLink | null;
|
||||
public readonly text: string | null;
|
||||
public readonly urlDestination: string | null;
|
||||
export function linkTagNode(linkNode: DocLinkTag, model: ApiModel, parentItem?: ApiItem): DocLinkTagJSON {
|
||||
const codeDestination =
|
||||
linkNode.codeDestination && parentItem ? genToken(model, linkNode.codeDestination, parentItem) : null;
|
||||
const text = linkNode.linkText ?? null;
|
||||
const urlDestination = linkNode.urlDestination ?? null;
|
||||
|
||||
public constructor(node: DocLinkTag, model: ApiModel, parentItem?: ApiItem) {
|
||||
super(node, model, parentItem);
|
||||
this.codeDestination = node.codeDestination ? genToken(model, node.codeDestination, this.parentItem) : null;
|
||||
this.text = node.linkText ?? null;
|
||||
this.urlDestination = node.urlDestination ?? null;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
text: this.text,
|
||||
codeDestination: this.codeDestination,
|
||||
urlDestination: this.urlDestination,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...node(linkNode),
|
||||
text,
|
||||
codeDestination,
|
||||
urlDestination,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import type { DocPlainText } from '@microsoft/tsdoc';
|
||||
import { CommentNode } from './CommentNode';
|
||||
import { DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export class PlainTextCommentNode extends CommentNode<DocPlainText> {
|
||||
public readonly text: string;
|
||||
|
||||
public constructor(node: DocPlainText, model: ApiModel, parentItem?: ApiItem) {
|
||||
super(node, model, parentItem);
|
||||
this.text = node.text;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
text: this.text,
|
||||
};
|
||||
}
|
||||
export interface DocPlainTextJSON extends DocNodeJSON {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export function plainTextNode(plainTextNode: DocPlainText): DocPlainTextJSON {
|
||||
return {
|
||||
...node(plainTextNode),
|
||||
text: plainTextNode.text,
|
||||
};
|
||||
}
|
||||
|
||||
20
packages/website/src/DocModel/comment/RootComment.ts
Normal file
20
packages/website/src/DocModel/comment/RootComment.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import type { DocComment } from '@microsoft/tsdoc';
|
||||
import { createCommentNode } from '.';
|
||||
import { block, DocBlockJSON } from './CommentBlock';
|
||||
import { DocNodeJSON, node } from './CommentNode';
|
||||
|
||||
export interface DocCommentJSON extends DocNodeJSON {
|
||||
summary: DocNodeJSON[];
|
||||
remarks: DocNodeJSON[];
|
||||
customBlocks: DocBlockJSON[];
|
||||
}
|
||||
|
||||
export function comment(comment: DocComment, model: ApiModel, parentItem?: ApiItem): DocCommentJSON {
|
||||
return {
|
||||
...node(comment),
|
||||
summary: comment.summarySection.nodes.map((node) => createCommentNode(node, model, parentItem)),
|
||||
remarks: comment.remarksBlock?.content.nodes.map((node) => createCommentNode(node, model, parentItem)) ?? [],
|
||||
customBlocks: comment.customBlocks.map((_block) => block(_block, model, parentItem)),
|
||||
};
|
||||
}
|
||||
@@ -1,22 +1,43 @@
|
||||
import type { ApiModel, ApiItem } from '@microsoft/api-extractor-model';
|
||||
import type { DocNode, DocPlainText, DocLinkTag, DocParagraph, DocFencedCode } from '@microsoft/tsdoc';
|
||||
import { CommentNode } from './CommentNode';
|
||||
import { CommentNodeContainer } from './CommentNodeContainer';
|
||||
import { FencedCodeCommentNode } from './FencedCodeCommentNode';
|
||||
import { LinkTagCommentNode } from './LinkTagCommentNode';
|
||||
import { PlainTextCommentNode } from './PlainTextCommentNode';
|
||||
import {
|
||||
type DocNode,
|
||||
type DocPlainText,
|
||||
type DocLinkTag,
|
||||
type DocParagraph,
|
||||
type DocFencedCode,
|
||||
DocNodeKind,
|
||||
type DocBlock,
|
||||
DocComment,
|
||||
DocCodeSpan,
|
||||
} from '@microsoft/tsdoc';
|
||||
import { block } from './CommentBlock';
|
||||
import { codeSpan } from './CommentCodeSpan';
|
||||
import type { AnyDocNodeJSON } from './CommentNode';
|
||||
import { node as _node } from './CommentNode';
|
||||
import { nodeContainer } from './CommentNodeContainer';
|
||||
import { fencedCode } from './FencedCodeCommentNode';
|
||||
import { linkTagNode } from './LinkTagCommentNode';
|
||||
import { plainTextNode } from './PlainTextCommentNode';
|
||||
import { comment } from './RootComment';
|
||||
|
||||
export function createCommentNode(node: DocNode, model: ApiModel, parentItem?: ApiItem): CommentNode {
|
||||
export function createCommentNode(node: DocNode, model: ApiModel, parentItem?: ApiItem): AnyDocNodeJSON {
|
||||
switch (node.kind) {
|
||||
case 'PlainText':
|
||||
return new PlainTextCommentNode(node as DocPlainText, model, parentItem);
|
||||
case 'LinkTag':
|
||||
return new LinkTagCommentNode(node as DocLinkTag, model, parentItem);
|
||||
case 'Paragraph':
|
||||
return new CommentNodeContainer(node as DocParagraph, model, parentItem);
|
||||
case 'FencedCode':
|
||||
return new FencedCodeCommentNode(node as DocFencedCode, model, parentItem);
|
||||
case DocNodeKind.PlainText:
|
||||
return plainTextNode(node as DocPlainText);
|
||||
case DocNodeKind.LinkTag:
|
||||
return linkTagNode(node as DocLinkTag, model, parentItem);
|
||||
case DocNodeKind.Paragraph:
|
||||
case DocNodeKind.Section:
|
||||
return nodeContainer(node as DocParagraph, model, parentItem);
|
||||
case DocNodeKind.FencedCode:
|
||||
return fencedCode(node as DocFencedCode);
|
||||
case DocNodeKind.CodeSpan:
|
||||
return codeSpan(node as DocCodeSpan);
|
||||
case DocNodeKind.Block:
|
||||
return block(node as DocBlock, model, parentItem);
|
||||
case DocNodeKind.Comment:
|
||||
return comment(node as DocComment, model, parentItem);
|
||||
default:
|
||||
return new CommentNode(node, model, parentItem);
|
||||
return _node(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Group, Stack, Title } from '@mantine/core';
|
||||
import type { ReactNode } from 'react';
|
||||
import { CommentSection } from './Comment';
|
||||
import { HyperlinkedText } from './HyperlinkedText';
|
||||
import { TSDoc } from './tsdoc/TSDoc';
|
||||
import type { DocItem } from '~/DocModel/DocItem';
|
||||
import type { AnyDocNodeJSON } from '~/DocModel/comment/CommentNode';
|
||||
import type { TokenDocumentation } from '~/util/parse.server';
|
||||
|
||||
export enum CodeListingSeparatorType {
|
||||
@@ -16,6 +17,7 @@ export function CodeListing({
|
||||
summary,
|
||||
typeTokens,
|
||||
children,
|
||||
comment,
|
||||
}: {
|
||||
name: string;
|
||||
summary?: ReturnType<DocItem['toJSON']>['summary'];
|
||||
@@ -23,6 +25,7 @@ export function CodeListing({
|
||||
separator?: CodeListingSeparatorType;
|
||||
children?: ReactNode;
|
||||
className?: string | undefined;
|
||||
comment?: AnyDocNodeJSON | null;
|
||||
}) {
|
||||
return (
|
||||
<Stack key={name}>
|
||||
@@ -35,7 +38,8 @@ export function CodeListing({
|
||||
<HyperlinkedText tokens={typeTokens} />
|
||||
</Title>
|
||||
</Group>
|
||||
{summary && <CommentSection node={summary} />}
|
||||
{summary && <TSDoc node={summary} />}
|
||||
{comment && <TSDoc node={comment} />}
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import { Anchor, Box, Text } from '@mantine/core';
|
||||
import Link from 'next/link';
|
||||
import type { ReactNode } from 'react';
|
||||
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||
import type { CommentNode } from '~/DocModel/comment/CommentNode';
|
||||
import type { CommentNodeContainer } from '~/DocModel/comment/CommentNodeContainer';
|
||||
import type { FencedCodeCommentNode } from '~/DocModel/comment/FencedCodeCommentNode';
|
||||
import type { LinkTagCommentNode } from '~/DocModel/comment/LinkTagCommentNode';
|
||||
import type { PlainTextCommentNode } from '~/DocModel/comment/PlainTextCommentNode';
|
||||
|
||||
export function CommentSection({ node }: { node: ReturnType<CommentNode['toJSON']> }): JSX.Element {
|
||||
const createNode = (node: ReturnType<CommentNode['toJSON']>, idx?: number): ReactNode => {
|
||||
switch (node.kind) {
|
||||
case 'PlainText':
|
||||
return (
|
||||
<Text key={idx} span>
|
||||
{(node as ReturnType<PlainTextCommentNode['toJSON']>).text}
|
||||
</Text>
|
||||
);
|
||||
case 'Paragraph':
|
||||
return (
|
||||
<Text key={idx} inline>
|
||||
{(node as ReturnType<CommentNodeContainer['toJSON']>).nodes.map((node, idx) => createNode(node, idx))}
|
||||
</Text>
|
||||
);
|
||||
case 'SoftBreak':
|
||||
return <br key={idx} />;
|
||||
case 'LinkTag': {
|
||||
const { codeDestination, urlDestination, text } = node as ReturnType<LinkTagCommentNode['toJSON']>;
|
||||
|
||||
if (codeDestination) {
|
||||
return (
|
||||
<Link key={idx} href={codeDestination.path} passHref>
|
||||
<Anchor component="a" className="font-mono">
|
||||
{text ?? codeDestination.name}
|
||||
</Anchor>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
if (urlDestination) {
|
||||
return (
|
||||
<Link key={idx} href={urlDestination} passHref>
|
||||
<Anchor component="a" className="font-mono">
|
||||
{text ?? urlDestination}
|
||||
</Anchor>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
case 'FencedCodeBlock': {
|
||||
const { language, code } = node as ReturnType<FencedCodeCommentNode['toJSON']>;
|
||||
return (
|
||||
<SyntaxHighlighter
|
||||
key={idx}
|
||||
wrapLines
|
||||
wrapLongLines
|
||||
language={language}
|
||||
style={vscDarkPlus}
|
||||
codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}
|
||||
>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
{node.kind === 'Paragraph' || node.kind === 'Section' ? (
|
||||
<>{(node as CommentNodeContainer).nodes.map((node, idx) => createNode(node, idx))}</>
|
||||
) : (
|
||||
createNode(node)
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -5,11 +5,12 @@ import { VscListSelection, VscSymbolParameter } from 'react-icons/vsc';
|
||||
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||
import { CodeListingSeparatorType } from './CodeListing';
|
||||
import { CommentSection } from './Comment';
|
||||
import { HyperlinkedText } from './HyperlinkedText';
|
||||
import { Section } from './Section';
|
||||
import { TypeParamTable } from './TypeParamTable';
|
||||
import { TSDoc } from './tsdoc/TSDoc';
|
||||
import type { DocItem } from '~/DocModel/DocItem';
|
||||
import type { AnyDocNodeJSON } from '~/DocModel/comment/CommentNode';
|
||||
import { generateIcon } from '~/util/icon';
|
||||
import type { TokenDocumentation, TypeParameterData } from '~/util/parse.server';
|
||||
|
||||
@@ -22,6 +23,7 @@ export interface DocContainerProps {
|
||||
extendsTokens?: TokenDocumentation[] | null;
|
||||
implementsTokens?: TokenDocumentation[][];
|
||||
typeParams?: TypeParameterData[];
|
||||
comment?: AnyDocNodeJSON | null;
|
||||
}
|
||||
|
||||
export function DocContainer({
|
||||
@@ -46,7 +48,7 @@ export function DocContainer({
|
||||
</Title>
|
||||
|
||||
<Section title="Summary" icon={<VscListSelection />} padded dense={matches}>
|
||||
{summary ? <CommentSection node={summary} /> : <Text>No summary provided.</Text>}
|
||||
{summary ? <TSDoc node={summary} /> : <Text>No summary provided.</Text>}
|
||||
</Section>
|
||||
|
||||
<Box px="xs" pb="xs">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Group, Stack, Title } from '@mantine/core';
|
||||
import { CommentSection } from './Comment';
|
||||
import { HyperlinkedText } from './HyperlinkedText';
|
||||
import { ParameterTable } from './ParameterTable';
|
||||
import { TSDoc } from './tsdoc/TSDoc';
|
||||
import type { DocMethod } from '~/DocModel/DocMethod';
|
||||
import type { DocMethodSignature } from '~/DocModel/DocMethodSignature';
|
||||
|
||||
@@ -32,7 +32,8 @@ export function MethodItem({ data }: { data: MethodResolvable }) {
|
||||
</Stack>
|
||||
</Group>
|
||||
<Group sx={{ display: data.summary || data.parameters.length ? 'block' : 'none' }} mb="lg">
|
||||
{data.summary ? <CommentSection node={data.summary} /> : null}
|
||||
{data.summary ? <TSDoc node={data.summary} /> : null}
|
||||
{data.comment ? <TSDoc node={data.comment} /> : null}
|
||||
{data.parameters.length ? <ParameterTable data={data.parameters} /> : null}
|
||||
</Group>
|
||||
</Stack>
|
||||
|
||||
@@ -6,7 +6,13 @@ export function PropertyList({ data }: { data: ReturnType<DocProperty['toJSON']>
|
||||
return (
|
||||
<Stack>
|
||||
{data.map((prop) => (
|
||||
<CodeListing key={prop.name} name={prop.name} typeTokens={prop.propertyTypeTokens} summary={prop.summary} />
|
||||
<CodeListing
|
||||
key={prop.name}
|
||||
name={prop.name}
|
||||
typeTokens={prop.propertyTypeTokens}
|
||||
summary={prop.summary}
|
||||
comment={prop.comment}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export function Class({ data }: { data: ReturnType<DocClass['toJSON']> }) {
|
||||
typeParams={data.typeParameterData}
|
||||
extendsTokens={data.extendsTokens}
|
||||
implementsTokens={data.implementsTokens}
|
||||
comment={data.comment}
|
||||
>
|
||||
<PropertiesSection data={data.properties} />
|
||||
<MethodsSection data={data.methods} />
|
||||
|
||||
40
packages/website/src/components/tsdoc/BlockComment.tsx
Normal file
40
packages/website/src/components/tsdoc/BlockComment.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { StandardTags } from '@microsoft/tsdoc';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export interface BlockProps {
|
||||
children: ReactNode;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export function Block({ children, title }: BlockProps) {
|
||||
return (
|
||||
<div>
|
||||
<h3 className="m-0">{title}</h3>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export interface BlockCommentProps {
|
||||
tagName: string;
|
||||
children: ReactNode;
|
||||
index?: number | undefined;
|
||||
}
|
||||
|
||||
export interface ExampleBlockProps {
|
||||
children: ReactNode;
|
||||
exampleIndex?: number | undefined;
|
||||
}
|
||||
|
||||
export function ExampleBlock({ children, exampleIndex }: ExampleBlockProps): JSX.Element {
|
||||
return <Block title={`Example ${exampleIndex ? exampleIndex : ''}`}>{children}</Block>;
|
||||
}
|
||||
|
||||
export function BlockComment({ children, tagName, index }: BlockCommentProps): JSX.Element {
|
||||
switch (tagName.toUpperCase()) {
|
||||
case StandardTags.example.tagNameWithUpperCase:
|
||||
return <ExampleBlock exampleIndex={index}>{children}</ExampleBlock>;
|
||||
default: // TODO: Support more blocks in the future.
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
124
packages/website/src/components/tsdoc/TSDoc.tsx
Normal file
124
packages/website/src/components/tsdoc/TSDoc.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import { Anchor, Box, Text } from '@mantine/core';
|
||||
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
|
||||
import Link from 'next/link';
|
||||
import type { 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 (
|
||||
<Text key={idx} span>
|
||||
{(node as DocPlainTextJSON).text}
|
||||
</Text>
|
||||
);
|
||||
case DocNodeKind.Paragraph:
|
||||
return (
|
||||
<Text key={idx} inline>
|
||||
{(node as DocNodeContainerJSON).nodes.map((node, idx) => createNode(node, idx))}
|
||||
</Text>
|
||||
);
|
||||
case DocNodeKind.SoftBreak:
|
||||
return <br key={idx} />;
|
||||
case DocNodeKind.LinkTag: {
|
||||
const { codeDestination, urlDestination, text } = node as DocLinkTagJSON;
|
||||
|
||||
if (codeDestination) {
|
||||
return (
|
||||
<Link key={idx} href={codeDestination.path} passHref>
|
||||
<Anchor component="a" className="font-mono">
|
||||
{text ?? codeDestination.name}
|
||||
</Anchor>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
if (urlDestination) {
|
||||
return (
|
||||
<Link key={idx} href={urlDestination} passHref>
|
||||
<Anchor component="a" className="font-mono">
|
||||
{text ?? urlDestination}
|
||||
</Anchor>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
case DocNodeKind.CodeSpan: {
|
||||
const { code } = node as DocFencedCodeJSON;
|
||||
return (
|
||||
<pre key={idx} className="inline">
|
||||
{code}
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
case DocNodeKind.FencedCode: {
|
||||
const { language, code } = node as DocFencedCodeJSON;
|
||||
return (
|
||||
<SyntaxHighlighter
|
||||
key={idx}
|
||||
wrapLines
|
||||
wrapLongLines
|
||||
language={language}
|
||||
style={vscDarkPlus}
|
||||
codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}
|
||||
>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
);
|
||||
}
|
||||
case DocNodeKind.Block: {
|
||||
const { tag } = node as DocBlockJSON;
|
||||
|
||||
if (tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase) {
|
||||
exampleIndex++;
|
||||
}
|
||||
|
||||
const index = numberOfExamples > 1 ? exampleIndex : undefined;
|
||||
|
||||
return (
|
||||
<BlockComment tagName={tag.tagName} key={idx} index={index}>
|
||||
{(node as DocBlockJSON).content.map((node, idx) => createNode(node, idx))}
|
||||
</BlockComment>
|
||||
);
|
||||
}
|
||||
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 <div>{comment.customBlocks.map((node, idx) => createNode(node, idx))}</div>;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
{node.kind === 'Paragraph' || node.kind === 'Section' ? (
|
||||
<>{(node as DocNodeContainerJSON).nodes.map((node, idx) => createNode(node, idx))}</>
|
||||
) : (
|
||||
createNode(node)
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ export type Awaitable<T> = T | Promise<T>;
|
||||
|
||||
/**
|
||||
* Yields the numbers in the given range as an array
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* range({ start: 3, end: 5 }); // [3, 4, 5]
|
||||
|
||||
@@ -79,6 +79,7 @@ export interface OptionalWebSocketManagerOptions {
|
||||
/**
|
||||
* The ids of the shards this WebSocketManager should manage.
|
||||
* Use `null` to simply spawn 0 through `shardCount - 1`
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* const manager = new WebSocketManager({
|
||||
|
||||
Reference in New Issue
Block a user