mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-11 00:53:31 +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,8 @@
|
||||
import type { PropsWithChildren } from 'react';
|
||||
|
||||
/**
|
||||
* Layout parent of documentation pages.
|
||||
*/
|
||||
export function Documentation({ children }: PropsWithChildren) {
|
||||
return <div className="w-full flex-col space-y-4">{children}</div>;
|
||||
}
|
||||
36
apps/website/src/components/documentation/Header.tsx
Normal file
36
apps/website/src/components/documentation/Header.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
|
||||
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
|
||||
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
|
||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||
import { VscSymbolVariable } from '@react-icons/all-files/vsc/VscSymbolVariable';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
|
||||
function generateIcon(kind: ApiItemKind) {
|
||||
switch (kind) {
|
||||
case ApiItemKind.Class:
|
||||
return <VscSymbolClass />;
|
||||
case ApiItemKind.Function:
|
||||
case ApiItemKind.Method:
|
||||
return <VscSymbolMethod />;
|
||||
case ApiItemKind.Enum:
|
||||
return <VscSymbolEnum />;
|
||||
case ApiItemKind.Interface:
|
||||
return <VscSymbolInterface />;
|
||||
case ApiItemKind.TypeAlias:
|
||||
return <VscSymbolVariable />;
|
||||
default:
|
||||
return <VscSymbolMethod />;
|
||||
}
|
||||
}
|
||||
|
||||
export function Header({ kind, name }: PropsWithChildren<{ kind: ApiItemKind; name: string }>) {
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<h2 className="flex flex-row place-items-center gap-2 break-all text-2xl font-bold">
|
||||
<span>{generateIcon(kind)}</span>
|
||||
{name}
|
||||
</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
51
apps/website/src/components/documentation/HierarchyText.tsx
Normal file
51
apps/website/src/components/documentation/HierarchyText.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { ApiClass, ApiInterface, Excerpt } from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
import { ExcerptText } from '../ExcerptText';
|
||||
|
||||
export function HierarchyText({ item, type }: { item: ApiClass | ApiInterface; type: 'Extends' | 'Implements' }) {
|
||||
const model = item.getAssociatedModel()!;
|
||||
|
||||
if (
|
||||
(item.kind === ApiItemKind.Class &&
|
||||
(item as ApiClass).extendsType === undefined &&
|
||||
(item as ApiClass).implementsTypes.length === 0) ||
|
||||
(item.kind === ApiItemKind.Interface && !(item as ApiInterface).extendsTypes)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let excerpts: Excerpt[];
|
||||
|
||||
if (item.kind === ApiItemKind.Class) {
|
||||
if (type === 'Implements') {
|
||||
if ((item as ApiClass).implementsTypes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
excerpts = (item as ApiClass).implementsTypes.map((typeExcerpt) => typeExcerpt.excerpt);
|
||||
} else {
|
||||
if (!(item as ApiClass).extendsType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
excerpts = [(item as ApiClass).extendsType!.excerpt];
|
||||
}
|
||||
} else {
|
||||
if ((item as ApiInterface).extendsTypes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
excerpts = (item as ApiInterface).extendsTypes.map((typeExcerpt) => typeExcerpt.excerpt);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-row place-items-center gap-4">
|
||||
<h3 className="text-xl font-bold">{type}</h3>
|
||||
<span className="space-y-2 break-all font-mono">
|
||||
{excerpts.map((excerpt, index) => (
|
||||
<ExcerptText excerpt={excerpt} key={index} model={model} />
|
||||
))}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { ApiDeclaredItem, ApiItemContainerMixin, ApiTypeParameterListMixin } from '@microsoft/api-extractor-model';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Outline } from '../Outline';
|
||||
import { SyntaxHighlighter } from '../SyntaxHighlighter';
|
||||
import { Documentation } from './Documentation';
|
||||
import { MethodsSection } from './section/MethodsSection';
|
||||
import { PropertiesSection } from './section/PropertiesSection';
|
||||
import { SummarySection } from './section/SummarySection';
|
||||
import { TypeParameterSection } from './section/TypeParametersSection';
|
||||
import { hasProperties, hasMethods, serializeMembers } from './util';
|
||||
|
||||
export function MemberContainerDocumentation({
|
||||
item,
|
||||
version,
|
||||
subheading,
|
||||
}: {
|
||||
item: ApiDeclaredItem & ApiItemContainerMixin & ApiTypeParameterListMixin;
|
||||
subheading?: ReactNode;
|
||||
version: string;
|
||||
}) {
|
||||
return (
|
||||
<Documentation item={item}>
|
||||
{subheading}
|
||||
<SyntaxHighlighter code={item.excerpt.text} />
|
||||
<SummarySection item={item} />
|
||||
{item.typeParameters.length ? <TypeParameterSection item={item} /> : null}
|
||||
{hasProperties(item) ? <PropertiesSection item={item} /> : null}
|
||||
{hasMethods(item) ? <MethodsSection item={item} /> : null}
|
||||
|
||||
<Outline members={serializeMembers(item)} />
|
||||
</Documentation>
|
||||
);
|
||||
}
|
||||
13
apps/website/src/components/documentation/Members.tsx
Normal file
13
apps/website/src/components/documentation/Members.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { ApiDeclaredItem, ApiItemContainerMixin } from '@microsoft/api-extractor-model';
|
||||
import { MethodsSection } from './section/MethodsSection';
|
||||
import { PropertiesSection } from './section/PropertiesSection';
|
||||
import { hasProperties, hasMethods } from './util';
|
||||
|
||||
export function Members({ item }: { item: ApiDeclaredItem & ApiItemContainerMixin }) {
|
||||
return (
|
||||
<>
|
||||
{hasProperties(item) ? <PropertiesSection item={item} /> : null}
|
||||
{hasMethods(item) ? <MethodsSection item={item} /> : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
18
apps/website/src/components/documentation/ObjectHeader.tsx
Normal file
18
apps/website/src/components/documentation/ObjectHeader.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { ApiDeclaredItem, ApiItemContainerMixin } from '@microsoft/api-extractor-model';
|
||||
import { SyntaxHighlighter } from '../SyntaxHighlighter';
|
||||
import { Header } from './Header';
|
||||
import { SummarySection } from './section/SummarySection';
|
||||
|
||||
export interface ObjectHeaderProps {
|
||||
item: ApiDeclaredItem & ApiItemContainerMixin;
|
||||
}
|
||||
|
||||
export function ObjectHeader({ item }: ObjectHeaderProps) {
|
||||
return (
|
||||
<>
|
||||
<Header kind={item.kind} name={item.displayName} />
|
||||
<SyntaxHighlighter code={item.excerpt.text} />
|
||||
<SummarySection item={item} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { ApiConstructor } from '@microsoft/api-extractor-model';
|
||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||
import { useCallback } from 'react';
|
||||
import { TSDoc } from '../tsdoc/TSDoc';
|
||||
import { ResponsiveSection } from './ResponsiveSection';
|
||||
import { ParameterTable } from '~/components/ParameterTable';
|
||||
|
||||
export function ConstructorSection({ item }: { item: ApiConstructor }) {
|
||||
const getShorthandName = useCallback(
|
||||
(ctor: ApiConstructor) =>
|
||||
`constructor(${ctor.parameters.reduce((prev, cur, index) => {
|
||||
if (index === 0) {
|
||||
return `${prev}${cur.isOptional ? `${cur.name}?` : cur.name}`;
|
||||
}
|
||||
|
||||
return `${prev}, ${cur.isOptional ? `${cur.name}?` : cur.name}`;
|
||||
}, '')})`,
|
||||
[],
|
||||
);
|
||||
|
||||
return (
|
||||
<ResponsiveSection icon={<VscSymbolMethod size={20} />} padded title="Constructor">
|
||||
<div className="flex flex-col gap-2">
|
||||
<h4 className="break-all font-mono text-lg font-bold">{getShorthandName(item)}</h4>
|
||||
{item.tsdocComment ? <TSDoc item={item} tsdoc={item.tsdocComment} /> : null}
|
||||
<ParameterTable item={item} />
|
||||
</div>
|
||||
</ResponsiveSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import type {
|
||||
ApiDeclaredItem,
|
||||
ApiItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiMethod,
|
||||
ApiMethodSignature,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
|
||||
import { useMemo, Fragment } from 'react';
|
||||
import { ResponsiveSection } from './ResponsiveSection';
|
||||
import { Method } from '~/components/model/method/Method';
|
||||
import { resolveMembers } from '~/util/members';
|
||||
|
||||
function isMethodLike(item: ApiItem): item is ApiMethod | ApiMethodSignature {
|
||||
return (
|
||||
item.kind === ApiItemKind.Method ||
|
||||
(item.kind === ApiItemKind.MethodSignature && (item as ApiMethod).overloadIndex <= 1)
|
||||
);
|
||||
}
|
||||
|
||||
export function MethodsSection({ item }: { item: ApiItemContainerMixin }) {
|
||||
const members = resolveMembers(item, isMethodLike);
|
||||
|
||||
const methodItems = useMemo(
|
||||
() =>
|
||||
members.map(({ item: method, inherited }) => (
|
||||
<Fragment
|
||||
key={`${method.displayName}${
|
||||
method.overloadIndex && method.overloadIndex > 1 ? `:${(method as ApiMethod).overloadIndex}` : ''
|
||||
}`}
|
||||
>
|
||||
<Method inheritedFrom={inherited as ApiDeclaredItem & ApiItemContainerMixin} method={method} />
|
||||
<div className="border-light-900 dark:border-dark-100 -mx-8 border-t-2" />
|
||||
</Fragment>
|
||||
)),
|
||||
[members],
|
||||
);
|
||||
|
||||
return (
|
||||
<ResponsiveSection icon={<VscSymbolMethod size={20} />} padded title="Methods">
|
||||
<div className="flex flex-col gap-4">{methodItems}</div>
|
||||
</ResponsiveSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { ApiParameterListMixin } from '@microsoft/api-extractor-model';
|
||||
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
|
||||
import { ResponsiveSection } from './ResponsiveSection';
|
||||
import { ParameterTable } from '~/components/ParameterTable';
|
||||
|
||||
export function ParameterSection({ item }: { item: ApiParameterListMixin }) {
|
||||
return (
|
||||
<ResponsiveSection icon={<VscSymbolParameter size={20} />} padded title="Parameters">
|
||||
<ParameterTable item={item} />
|
||||
</ResponsiveSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { ApiItemContainerMixin } from '@microsoft/api-extractor-model';
|
||||
import { VscSymbolProperty } from '@react-icons/all-files/vsc/VscSymbolProperty';
|
||||
import { ResponsiveSection } from './ResponsiveSection';
|
||||
import { PropertyList } from '~/components/PropertyList';
|
||||
|
||||
export function PropertiesSection({ item }: { item: ApiItemContainerMixin }) {
|
||||
return (
|
||||
<ResponsiveSection icon={<VscSymbolProperty size={20} />} padded title="Properties">
|
||||
<PropertyList item={item} />
|
||||
</ResponsiveSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
'use client';
|
||||
|
||||
import type { SectionOptions } from '@discordjs/ui';
|
||||
import { Section } from '@discordjs/ui';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { useMedia } from 'react-use';
|
||||
|
||||
export function ResponsiveSection(opts: PropsWithChildren<SectionOptions & { separator?: boolean }>) {
|
||||
const matches = useMedia('(max-width: 768px)', true);
|
||||
|
||||
const { children, separator, ...rest } = opts;
|
||||
|
||||
const props = {
|
||||
...rest,
|
||||
dense: matches,
|
||||
};
|
||||
|
||||
return (
|
||||
<Section {...props}>
|
||||
{children}
|
||||
{separator ? <div className="border-light-900 dark:border-dark-100 -mx-8 mt-6 border-t-2" /> : null}
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
||||
import { VscListSelection } from '@react-icons/all-files/vsc/VscListSelection';
|
||||
import { TSDoc } from '../tsdoc/TSDoc';
|
||||
import { ResponsiveSection } from './ResponsiveSection';
|
||||
|
||||
export function SummarySection({ item }: { item: ApiDeclaredItem }) {
|
||||
return (
|
||||
<ResponsiveSection icon={<VscListSelection size={20} />} padded separator title="Summary">
|
||||
{item.tsdocComment?.summarySection ? (
|
||||
<TSDoc item={item} tsdoc={item.tsdocComment} />
|
||||
) : (
|
||||
<p>No summary provided.</p>
|
||||
)}
|
||||
</ResponsiveSection>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { ApiTypeParameterListMixin } from '@microsoft/api-extractor-model';
|
||||
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
|
||||
import { ResponsiveSection } from './ResponsiveSection';
|
||||
import { TypeParamTable } from '~/components/TypeParamTable';
|
||||
|
||||
export function TypeParameterSection({ item }: { item: ApiTypeParameterListMixin }) {
|
||||
return (
|
||||
<ResponsiveSection icon={<VscSymbolParameter size={20} />} padded title="Type Parameters">
|
||||
<TypeParamTable item={item} />
|
||||
</ResponsiveSection>
|
||||
);
|
||||
}
|
||||
@@ -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)
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
53
apps/website/src/components/documentation/util.ts
Normal file
53
apps/website/src/components/documentation/util.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { ApiItemKind } from '@microsoft/api-extractor-model';
|
||||
import type {
|
||||
ApiItem,
|
||||
ApiItemContainerMixin,
|
||||
ApiMethod,
|
||||
ApiMethodSignature,
|
||||
ApiProperty,
|
||||
ApiPropertySignature,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import type { TableOfContentsSerialized } from '../TableOfContentItems';
|
||||
import { resolveMembers } from '~/util/members';
|
||||
|
||||
export function hasProperties(item: ApiItemContainerMixin) {
|
||||
return resolveMembers(item, memberPredicate).some(
|
||||
({ item: member }) => member.kind === ApiItemKind.Property || member.kind === ApiItemKind.PropertySignature,
|
||||
);
|
||||
}
|
||||
|
||||
export function hasMethods(item: ApiItemContainerMixin) {
|
||||
return resolveMembers(item, memberPredicate).some(
|
||||
({ item: member }) => member.kind === ApiItemKind.Method || member.kind === ApiItemKind.MethodSignature,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveItemURI(item: ApiItem): string {
|
||||
return `/${item.displayName}:${item.kind}`;
|
||||
}
|
||||
|
||||
function memberPredicate(item: ApiItem): item is ApiMethod | ApiMethodSignature | ApiProperty | ApiPropertySignature {
|
||||
return (
|
||||
item.kind === ApiItemKind.Property ||
|
||||
item.kind === ApiItemKind.PropertySignature ||
|
||||
item.kind === ApiItemKind.Method ||
|
||||
item.kind === ApiItemKind.MethodSignature
|
||||
);
|
||||
}
|
||||
|
||||
export function serializeMembers(clazz: ApiItemContainerMixin): TableOfContentsSerialized[] {
|
||||
return resolveMembers(clazz, memberPredicate).map(({ item: member }) => {
|
||||
if (member.kind === 'Method' || member.kind === 'MethodSignature') {
|
||||
return {
|
||||
kind: member.kind as 'Method' | 'MethodSignature',
|
||||
name: member.displayName,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
kind: member.kind as 'Property' | 'PropertySignature',
|
||||
name: member.displayName,
|
||||
overloadIndex: (member as ApiMethod | ApiMethodSignature).overloadIndex,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user