mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-16 11:33:30 +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 type { ApiEnum, ApiModel } from '@microsoft/api-extractor-model';
|
||||||
import { DocItem } from './DocItem';
|
import { DocItem } from './DocItem';
|
||||||
import { CommentNodeContainer } from './comment/CommentNodeContainer';
|
import { nodeContainer } from './comment/CommentNodeContainer';
|
||||||
import { genToken, TokenDocumentation } from '~/util/parse.server';
|
import { genToken, TokenDocumentation } from '~/util/parse.server';
|
||||||
|
|
||||||
export interface EnumMemberData {
|
export interface EnumMemberData {
|
||||||
@@ -18,9 +18,7 @@ export class DocEnum extends DocItem<ApiEnum> {
|
|||||||
this.members = item.members.map((member) => ({
|
this.members = item.members.map((member) => ({
|
||||||
name: member.name,
|
name: member.name,
|
||||||
initializerTokens: member.initializerExcerpt?.spannedTokens.map((token) => genToken(this.model, token)) ?? [],
|
initializerTokens: member.initializerExcerpt?.spannedTokens.map((token) => genToken(this.model, token)) ?? [],
|
||||||
summary: member.tsdocComment
|
summary: member.tsdocComment ? nodeContainer(member.tsdocComment.summarySection, model, member) : null,
|
||||||
? new CommentNodeContainer(member.tsdocComment.summarySection, model, member).toJSON()
|
|
||||||
: null,
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import type { ApiModel, ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
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 type { ReferenceData } from '~/util/model.server';
|
||||||
import { resolveName, genReference, TokenDocumentation, genToken } from '~/util/parse.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 excerpt: string;
|
||||||
public readonly excerptTokens: TokenDocumentation[] = [];
|
public readonly excerptTokens: TokenDocumentation[] = [];
|
||||||
public readonly kind: string;
|
public readonly kind: string;
|
||||||
public readonly remarks: CommentNodeContainer | null;
|
public readonly remarks: DocNodeContainerJSON | null;
|
||||||
public readonly summary: CommentNodeContainer | null;
|
public readonly summary: DocNodeContainerJSON | null;
|
||||||
public readonly containerKey: string;
|
public readonly containerKey: string;
|
||||||
|
public readonly comment: AnyDocNodeJSON | null;
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: T) {
|
public constructor(model: ApiModel, item: T) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
@@ -26,12 +29,13 @@ export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
|||||||
this.excerpt = item.excerpt.text;
|
this.excerpt = item.excerpt.text;
|
||||||
this.excerptTokens = item.excerpt.spannedTokens.map((token) => genToken(model, token));
|
this.excerptTokens = item.excerpt.spannedTokens.map((token) => genToken(model, token));
|
||||||
this.remarks = item.tsdocComment?.remarksBlock
|
this.remarks = item.tsdocComment?.remarksBlock
|
||||||
? new CommentNodeContainer(item.tsdocComment.remarksBlock.content, model, item.parent)
|
? (createCommentNode(item.tsdocComment.remarksBlock, model, item.parent) as DocNodeContainerJSON)
|
||||||
: null;
|
: null;
|
||||||
this.summary = item.tsdocComment?.summarySection
|
this.summary = item.tsdocComment?.summarySection
|
||||||
? new CommentNodeContainer(item.tsdocComment.summarySection, model, item.parent)
|
? (createCommentNode(item.tsdocComment.summarySection, model, item.parent) as DocNodeContainerJSON)
|
||||||
: null;
|
: null;
|
||||||
this.containerKey = item.containerKey;
|
this.containerKey = item.containerKey;
|
||||||
|
this.comment = item.tsdocComment ? createCommentNode(item.tsdocComment, model, item.parent) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get path() {
|
public get path() {
|
||||||
@@ -54,13 +58,14 @@ export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
|||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
referenceData: this.referenceData,
|
referenceData: this.referenceData,
|
||||||
summary: this.summary?.toJSON() ?? null,
|
summary: this.summary,
|
||||||
excerpt: this.excerpt,
|
excerpt: this.excerpt,
|
||||||
excerptTokens: this.excerptTokens,
|
excerptTokens: this.excerptTokens,
|
||||||
kind: this.kind,
|
kind: this.kind,
|
||||||
remarks: this.remarks?.toJSON() ?? null,
|
remarks: this.remarks,
|
||||||
path: this.path,
|
path: this.path,
|
||||||
containerKey: this.containerKey,
|
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, DocNodeKind } from '@microsoft/tsdoc';
|
||||||
import type { DocNode } 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> {
|
export interface DocNodeJSON {
|
||||||
public readonly node: T;
|
kind: DocNodeKind;
|
||||||
public readonly kind: string;
|
}
|
||||||
public readonly model: ApiModel;
|
|
||||||
public readonly parentItem: ApiItem | null;
|
export type AnyDocNodeJSON =
|
||||||
|
| DocNodeJSON
|
||||||
public constructor(node: T, model: ApiModel, parentItem?: ApiItem) {
|
| DocPlainTextJSON
|
||||||
this.node = node;
|
| DocNodeContainerJSON
|
||||||
this.kind = node.kind;
|
| DocLinkTagJSON
|
||||||
this.model = model;
|
| DocFencedCodeJSON
|
||||||
this.parentItem = parentItem ?? null;
|
| DocBlockJSON
|
||||||
}
|
| DocCommentJSON
|
||||||
|
| DocCodeSpanJSON;
|
||||||
public toJSON() {
|
|
||||||
return {
|
export function node(node: DocNode): DocNodeJSON {
|
||||||
kind: this.kind,
|
return {
|
||||||
};
|
kind: node.kind as DocNodeKind,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||||
import type { DocNodeContainer } from '@microsoft/tsdoc';
|
import type { DocNodeContainer } from '@microsoft/tsdoc';
|
||||||
import { createCommentNode } from '.';
|
import { createCommentNode } from '.';
|
||||||
import { CommentNode } from './CommentNode';
|
import { AnyDocNodeJSON, DocNodeJSON, node } from './CommentNode';
|
||||||
|
|
||||||
export class CommentNodeContainer<T extends DocNodeContainer = DocNodeContainer> extends CommentNode<DocNodeContainer> {
|
export interface DocNodeContainerJSON extends DocNodeJSON {
|
||||||
public readonly nodes: CommentNode[];
|
nodes: AnyDocNodeJSON[];
|
||||||
|
}
|
||||||
public constructor(container: T, model: ApiModel, parentItem?: ApiItem) {
|
|
||||||
super(container, model, parentItem);
|
export function nodeContainer(
|
||||||
this.nodes = container.nodes.map((node) => createCommentNode(node, model, parentItem));
|
container: DocNodeContainer,
|
||||||
}
|
model: ApiModel,
|
||||||
|
parentItem?: ApiItem,
|
||||||
public override toJSON() {
|
): DocNodeContainerJSON {
|
||||||
return {
|
return {
|
||||||
...super.toJSON(),
|
...node(container),
|
||||||
nodes: this.nodes.map((node) => node.toJSON()),
|
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 type { DocFencedCode } from '@microsoft/tsdoc';
|
||||||
import { CommentNode } from './CommentNode';
|
import { DocNodeJSON, node } from './CommentNode';
|
||||||
|
|
||||||
export class FencedCodeCommentNode extends CommentNode<DocFencedCode> {
|
export interface DocFencedCodeJSON extends DocNodeJSON {
|
||||||
public readonly code: string;
|
code: string;
|
||||||
public readonly language: string;
|
language: string;
|
||||||
|
}
|
||||||
public constructor(node: DocFencedCode, model: ApiModel, parentItem?: ApiItem) {
|
|
||||||
super(node, model, parentItem);
|
export function fencedCode(fencedCode: DocFencedCode) {
|
||||||
this.code = node.code;
|
return {
|
||||||
this.language = node.language;
|
...node(fencedCode),
|
||||||
}
|
language: fencedCode.language,
|
||||||
|
code: fencedCode.code,
|
||||||
public override toJSON() {
|
};
|
||||||
return {
|
|
||||||
...super.toJSON(),
|
|
||||||
code: this.code,
|
|
||||||
language: this.language,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
||||||
import type { DocDeclarationReference, DocLinkTag } from '@microsoft/tsdoc';
|
import type { DocDeclarationReference, DocLinkTag } from '@microsoft/tsdoc';
|
||||||
import { CommentNode } from './CommentNode';
|
import { DocNodeJSON, node } from './CommentNode';
|
||||||
import { generatePath, resolveName } from '~/util/parse.server';
|
import { generatePath, resolveName } from '~/util/parse.server';
|
||||||
|
|
||||||
|
export interface DocLinkTagJSON extends DocNodeJSON {
|
||||||
|
text: string | null;
|
||||||
|
codeDestination: LinkTagCodeLink | null;
|
||||||
|
urlDestination: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export function genToken(
|
export function genToken(
|
||||||
model: ApiModel,
|
model: ApiModel,
|
||||||
ref: DocDeclarationReference,
|
ref: DocDeclarationReference,
|
||||||
@@ -31,24 +37,16 @@ export interface LinkTagCodeLink {
|
|||||||
path: string;
|
path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LinkTagCommentNode extends CommentNode<DocLinkTag> {
|
export function linkTagNode(linkNode: DocLinkTag, model: ApiModel, parentItem?: ApiItem): DocLinkTagJSON {
|
||||||
public readonly codeDestination: LinkTagCodeLink | null;
|
const codeDestination =
|
||||||
public readonly text: string | null;
|
linkNode.codeDestination && parentItem ? genToken(model, linkNode.codeDestination, parentItem) : null;
|
||||||
public readonly urlDestination: string | null;
|
const text = linkNode.linkText ?? null;
|
||||||
|
const urlDestination = linkNode.urlDestination ?? null;
|
||||||
|
|
||||||
public constructor(node: DocLinkTag, model: ApiModel, parentItem?: ApiItem) {
|
return {
|
||||||
super(node, model, parentItem);
|
...node(linkNode),
|
||||||
this.codeDestination = node.codeDestination ? genToken(model, node.codeDestination, this.parentItem) : null;
|
text,
|
||||||
this.text = node.linkText ?? null;
|
codeDestination,
|
||||||
this.urlDestination = node.urlDestination ?? null;
|
urlDestination,
|
||||||
}
|
};
|
||||||
|
|
||||||
public override toJSON() {
|
|
||||||
return {
|
|
||||||
...super.toJSON(),
|
|
||||||
text: this.text,
|
|
||||||
codeDestination: this.codeDestination,
|
|
||||||
urlDestination: this.urlDestination,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,13 @@
|
|||||||
import type { ApiItem, ApiModel } from '@microsoft/api-extractor-model';
|
|
||||||
import type { DocPlainText } from '@microsoft/tsdoc';
|
import type { DocPlainText } from '@microsoft/tsdoc';
|
||||||
import { CommentNode } from './CommentNode';
|
import { DocNodeJSON, node } from './CommentNode';
|
||||||
|
|
||||||
export class PlainTextCommentNode extends CommentNode<DocPlainText> {
|
export interface DocPlainTextJSON extends DocNodeJSON {
|
||||||
public readonly text: string;
|
text: string;
|
||||||
|
}
|
||||||
public constructor(node: DocPlainText, model: ApiModel, parentItem?: ApiItem) {
|
|
||||||
super(node, model, parentItem);
|
export function plainTextNode(plainTextNode: DocPlainText): DocPlainTextJSON {
|
||||||
this.text = node.text;
|
return {
|
||||||
}
|
...node(plainTextNode),
|
||||||
|
text: plainTextNode.text,
|
||||||
public override toJSON() {
|
};
|
||||||
return {
|
|
||||||
...super.toJSON(),
|
|
||||||
text: this.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 { ApiModel, ApiItem } from '@microsoft/api-extractor-model';
|
||||||
import type { DocNode, DocPlainText, DocLinkTag, DocParagraph, DocFencedCode } from '@microsoft/tsdoc';
|
import {
|
||||||
import { CommentNode } from './CommentNode';
|
type DocNode,
|
||||||
import { CommentNodeContainer } from './CommentNodeContainer';
|
type DocPlainText,
|
||||||
import { FencedCodeCommentNode } from './FencedCodeCommentNode';
|
type DocLinkTag,
|
||||||
import { LinkTagCommentNode } from './LinkTagCommentNode';
|
type DocParagraph,
|
||||||
import { PlainTextCommentNode } from './PlainTextCommentNode';
|
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) {
|
switch (node.kind) {
|
||||||
case 'PlainText':
|
case DocNodeKind.PlainText:
|
||||||
return new PlainTextCommentNode(node as DocPlainText, model, parentItem);
|
return plainTextNode(node as DocPlainText);
|
||||||
case 'LinkTag':
|
case DocNodeKind.LinkTag:
|
||||||
return new LinkTagCommentNode(node as DocLinkTag, model, parentItem);
|
return linkTagNode(node as DocLinkTag, model, parentItem);
|
||||||
case 'Paragraph':
|
case DocNodeKind.Paragraph:
|
||||||
return new CommentNodeContainer(node as DocParagraph, model, parentItem);
|
case DocNodeKind.Section:
|
||||||
case 'FencedCode':
|
return nodeContainer(node as DocParagraph, model, parentItem);
|
||||||
return new FencedCodeCommentNode(node as DocFencedCode, 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:
|
default:
|
||||||
return new CommentNode(node, model, parentItem);
|
return _node(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Group, Stack, Title } from '@mantine/core';
|
import { Group, Stack, Title } from '@mantine/core';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { CommentSection } from './Comment';
|
|
||||||
import { HyperlinkedText } from './HyperlinkedText';
|
import { HyperlinkedText } from './HyperlinkedText';
|
||||||
|
import { TSDoc } from './tsdoc/TSDoc';
|
||||||
import type { DocItem } from '~/DocModel/DocItem';
|
import type { DocItem } from '~/DocModel/DocItem';
|
||||||
|
import type { AnyDocNodeJSON } from '~/DocModel/comment/CommentNode';
|
||||||
import type { TokenDocumentation } from '~/util/parse.server';
|
import type { TokenDocumentation } from '~/util/parse.server';
|
||||||
|
|
||||||
export enum CodeListingSeparatorType {
|
export enum CodeListingSeparatorType {
|
||||||
@@ -16,6 +17,7 @@ export function CodeListing({
|
|||||||
summary,
|
summary,
|
||||||
typeTokens,
|
typeTokens,
|
||||||
children,
|
children,
|
||||||
|
comment,
|
||||||
}: {
|
}: {
|
||||||
name: string;
|
name: string;
|
||||||
summary?: ReturnType<DocItem['toJSON']>['summary'];
|
summary?: ReturnType<DocItem['toJSON']>['summary'];
|
||||||
@@ -23,6 +25,7 @@ export function CodeListing({
|
|||||||
separator?: CodeListingSeparatorType;
|
separator?: CodeListingSeparatorType;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
className?: string | undefined;
|
className?: string | undefined;
|
||||||
|
comment?: AnyDocNodeJSON | null;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Stack key={name}>
|
<Stack key={name}>
|
||||||
@@ -35,7 +38,8 @@ export function CodeListing({
|
|||||||
<HyperlinkedText tokens={typeTokens} />
|
<HyperlinkedText tokens={typeTokens} />
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
{summary && <CommentSection node={summary} />}
|
{summary && <TSDoc node={summary} />}
|
||||||
|
{comment && <TSDoc node={comment} />}
|
||||||
{children}
|
{children}
|
||||||
</Stack>
|
</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 { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||||
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||||
import { CodeListingSeparatorType } from './CodeListing';
|
import { CodeListingSeparatorType } from './CodeListing';
|
||||||
import { CommentSection } from './Comment';
|
|
||||||
import { HyperlinkedText } from './HyperlinkedText';
|
import { HyperlinkedText } from './HyperlinkedText';
|
||||||
import { Section } from './Section';
|
import { Section } from './Section';
|
||||||
import { TypeParamTable } from './TypeParamTable';
|
import { TypeParamTable } from './TypeParamTable';
|
||||||
|
import { TSDoc } from './tsdoc/TSDoc';
|
||||||
import type { DocItem } from '~/DocModel/DocItem';
|
import type { DocItem } from '~/DocModel/DocItem';
|
||||||
|
import type { AnyDocNodeJSON } from '~/DocModel/comment/CommentNode';
|
||||||
import { generateIcon } from '~/util/icon';
|
import { generateIcon } from '~/util/icon';
|
||||||
import type { TokenDocumentation, TypeParameterData } from '~/util/parse.server';
|
import type { TokenDocumentation, TypeParameterData } from '~/util/parse.server';
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ export interface DocContainerProps {
|
|||||||
extendsTokens?: TokenDocumentation[] | null;
|
extendsTokens?: TokenDocumentation[] | null;
|
||||||
implementsTokens?: TokenDocumentation[][];
|
implementsTokens?: TokenDocumentation[][];
|
||||||
typeParams?: TypeParameterData[];
|
typeParams?: TypeParameterData[];
|
||||||
|
comment?: AnyDocNodeJSON | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DocContainer({
|
export function DocContainer({
|
||||||
@@ -46,7 +48,7 @@ export function DocContainer({
|
|||||||
</Title>
|
</Title>
|
||||||
|
|
||||||
<Section title="Summary" icon={<VscListSelection />} padded dense={matches}>
|
<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>
|
</Section>
|
||||||
|
|
||||||
<Box px="xs" pb="xs">
|
<Box px="xs" pb="xs">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Group, Stack, Title } from '@mantine/core';
|
import { Group, Stack, Title } from '@mantine/core';
|
||||||
import { CommentSection } from './Comment';
|
|
||||||
import { HyperlinkedText } from './HyperlinkedText';
|
import { HyperlinkedText } from './HyperlinkedText';
|
||||||
import { ParameterTable } from './ParameterTable';
|
import { ParameterTable } from './ParameterTable';
|
||||||
|
import { TSDoc } from './tsdoc/TSDoc';
|
||||||
import type { DocMethod } from '~/DocModel/DocMethod';
|
import type { DocMethod } from '~/DocModel/DocMethod';
|
||||||
import type { DocMethodSignature } from '~/DocModel/DocMethodSignature';
|
import type { DocMethodSignature } from '~/DocModel/DocMethodSignature';
|
||||||
|
|
||||||
@@ -32,7 +32,8 @@ export function MethodItem({ data }: { data: MethodResolvable }) {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
<Group sx={{ display: data.summary || data.parameters.length ? 'block' : 'none' }} mb="lg">
|
<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}
|
{data.parameters.length ? <ParameterTable data={data.parameters} /> : null}
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ export function PropertyList({ data }: { data: ReturnType<DocProperty['toJSON']>
|
|||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
{data.map((prop) => (
|
{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>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export function Class({ data }: { data: ReturnType<DocClass['toJSON']> }) {
|
|||||||
typeParams={data.typeParameterData}
|
typeParams={data.typeParameterData}
|
||||||
extendsTokens={data.extendsTokens}
|
extendsTokens={data.extendsTokens}
|
||||||
implementsTokens={data.implementsTokens}
|
implementsTokens={data.implementsTokens}
|
||||||
|
comment={data.comment}
|
||||||
>
|
>
|
||||||
<PropertiesSection data={data.properties} />
|
<PropertiesSection data={data.properties} />
|
||||||
<MethodsSection data={data.methods} />
|
<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
|
* Yields the numbers in the given range as an array
|
||||||
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```
|
* ```
|
||||||
* range({ start: 3, end: 5 }); // [3, 4, 5]
|
* range({ start: 3, end: 5 }); // [3, 4, 5]
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ export interface OptionalWebSocketManagerOptions {
|
|||||||
/**
|
/**
|
||||||
* The ids of the shards this WebSocketManager should manage.
|
* The ids of the shards this WebSocketManager should manage.
|
||||||
* Use `null` to simply spawn 0 through `shardCount - 1`
|
* Use `null` to simply spawn 0 through `shardCount - 1`
|
||||||
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```
|
* ```
|
||||||
* const manager = new WebSocketManager({
|
* const manager = new WebSocketManager({
|
||||||
|
|||||||
Reference in New Issue
Block a user