mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-18 04:23:31 +01:00
feat(website): show package members in a sidebar (#8245)
* feat(website): show package members in a sidebar * fix: put response instead of loader * Apply suggestions from code review Co-authored-by: Noel <buechler.noel@outlook.com> * chore: make requested changes * refactor: make only package list scrollable * feat: make sidebar mobile responsive * fix: breakpoints for sidebar Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
@@ -8,14 +8,14 @@ import {
|
|||||||
import { DocItem } from './DocItem';
|
import { DocItem } from './DocItem';
|
||||||
import { DocMethod } from './DocMethod';
|
import { DocMethod } from './DocMethod';
|
||||||
import { DocProperty } from './DocProperty';
|
import { DocProperty } from './DocProperty';
|
||||||
import { type TokenDocumentation, genToken, TypeParameterData, generateTypeParamData } from '~/util/parse.server';
|
import { TypeParameterMixin } from './TypeParameterMixin';
|
||||||
|
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||||
|
|
||||||
export class DocClass extends DocItem<ApiClass> {
|
export class DocClass extends TypeParameterMixin(DocItem<ApiClass>) {
|
||||||
public readonly extendsTokens: TokenDocumentation[] | null;
|
public readonly extendsTokens: TokenDocumentation[] | null;
|
||||||
public readonly implementsTokens: TokenDocumentation[][];
|
public readonly implementsTokens: TokenDocumentation[][];
|
||||||
public readonly methods: DocMethod[] = [];
|
public readonly methods: DocMethod[] = [];
|
||||||
public readonly properties: DocProperty[] = [];
|
public readonly properties: DocProperty[] = [];
|
||||||
public readonly typeParameters: TypeParameterData[] = [];
|
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: ApiClass) {
|
public constructor(model: ApiModel, item: ApiClass) {
|
||||||
super(model, item);
|
super(model, item);
|
||||||
@@ -29,8 +29,6 @@ export class DocClass extends DocItem<ApiClass> {
|
|||||||
excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)),
|
excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(model, typeParam));
|
|
||||||
|
|
||||||
for (const member of item.members) {
|
for (const member of item.members) {
|
||||||
switch (member.kind) {
|
switch (member.kind) {
|
||||||
case ApiItemKind.Method:
|
case ApiItemKind.Method:
|
||||||
@@ -52,7 +50,6 @@ export class DocClass extends DocItem<ApiClass> {
|
|||||||
implementsTokens: this.implementsTokens,
|
implementsTokens: this.implementsTokens,
|
||||||
methods: this.methods.map((method) => method.toJSON()),
|
methods: this.methods.map((method) => method.toJSON()),
|
||||||
properties: this.properties.map((prop) => prop.toJSON()),
|
properties: this.properties.map((prop) => prop.toJSON()),
|
||||||
typeParameters: this.typeParameters,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,18 @@
|
|||||||
import type { ApiFunction, ApiModel } from '@microsoft/api-extractor-model';
|
import type { ApiFunction, ApiModel, ApiParameterListMixin } from '@microsoft/api-extractor-model';
|
||||||
import { DocItem } from './DocItem';
|
import { DocItem } from './DocItem';
|
||||||
import {
|
import { TypeParameterMixin } from './TypeParameterMixin';
|
||||||
type ParameterDocumentation,
|
import { type TokenDocumentation, genToken, genParameter, ParameterDocumentation } from '~/util/parse.server';
|
||||||
type TokenDocumentation,
|
|
||||||
genParameter,
|
|
||||||
genToken,
|
|
||||||
type TypeParameterData,
|
|
||||||
generateTypeParamData,
|
|
||||||
} from '~/util/parse.server';
|
|
||||||
|
|
||||||
export class DocFunction extends DocItem<ApiFunction> {
|
export class DocFunction extends TypeParameterMixin(DocItem<ApiFunction>) {
|
||||||
public readonly parameters: ParameterDocumentation[];
|
|
||||||
public readonly returnTypeTokens: TokenDocumentation[];
|
public readonly returnTypeTokens: TokenDocumentation[];
|
||||||
public readonly overloadIndex: number;
|
public readonly overloadIndex: number;
|
||||||
public readonly typeParameters: TypeParameterData[] = [];
|
public readonly parameters: ParameterDocumentation[];
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: ApiFunction) {
|
public constructor(model: ApiModel, item: ApiFunction) {
|
||||||
super(model, item);
|
super(model, item);
|
||||||
this.parameters = item.parameters.map((param) => genParameter(this.model, param));
|
|
||||||
this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
||||||
this.overloadIndex = item.overloadIndex;
|
this.overloadIndex = item.overloadIndex;
|
||||||
this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(model, typeParam));
|
this.parameters = (item as ApiParameterListMixin).parameters.map((param) => genParameter(this.model, param));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override toJSON() {
|
public override toJSON() {
|
||||||
@@ -29,7 +21,6 @@ export class DocFunction extends DocItem<ApiFunction> {
|
|||||||
parameters: this.parameters,
|
parameters: this.parameters,
|
||||||
returnTypeTokens: this.returnTypeTokens,
|
returnTypeTokens: this.returnTypeTokens,
|
||||||
overloadIndex: this.overloadIndex,
|
overloadIndex: this.overloadIndex,
|
||||||
typeParameters: this.typeParameters,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { DocItem } from './DocItem';
|
import { DocItem } from './DocItem';
|
||||||
import { DocMethodSignature } from './DocMethodSignature';
|
import { DocMethodSignature } from './DocMethodSignature';
|
||||||
import { DocProperty } from './DocProperty';
|
import { DocProperty } from './DocProperty';
|
||||||
|
import { TypeParameterMixin } from './TypeParameterMixin';
|
||||||
import { ApiInterface, ApiItemKind, ApiMethodSignature, ApiModel, ApiPropertySignature } from '~/api-extractor.server';
|
import { ApiInterface, ApiItemKind, ApiMethodSignature, ApiModel, ApiPropertySignature } from '~/api-extractor.server';
|
||||||
import { type TokenDocumentation, genToken, type TypeParameterData, generateTypeParamData } from '~/util/parse.server';
|
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||||
|
|
||||||
export class DocInterface extends DocItem<ApiInterface> {
|
export class DocInterface extends TypeParameterMixin(DocItem<ApiInterface>) {
|
||||||
public readonly extendsTokens: TokenDocumentation[][] | null;
|
public readonly extendsTokens: TokenDocumentation[][] | null;
|
||||||
public readonly methods: DocMethodSignature[] = [];
|
public readonly methods: DocMethodSignature[] = [];
|
||||||
public readonly properties: DocProperty[] = [];
|
public readonly properties: DocProperty[] = [];
|
||||||
public readonly typeParameters: TypeParameterData[] = [];
|
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: ApiInterface) {
|
public constructor(model: ApiModel, item: ApiInterface) {
|
||||||
super(model, item);
|
super(model, item);
|
||||||
@@ -17,8 +17,6 @@ export class DocInterface extends DocItem<ApiInterface> {
|
|||||||
excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)),
|
excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam));
|
|
||||||
|
|
||||||
for (const member of item.members) {
|
for (const member of item.members) {
|
||||||
switch (member.kind) {
|
switch (member.kind) {
|
||||||
case ApiItemKind.MethodSignature:
|
case ApiItemKind.MethodSignature:
|
||||||
@@ -39,7 +37,6 @@ export class DocInterface extends DocItem<ApiInterface> {
|
|||||||
extendsTokens: this.extendsTokens,
|
extendsTokens: this.extendsTokens,
|
||||||
methods: this.methods.map((method) => method.toJSON()),
|
methods: this.methods.map((method) => method.toJSON()),
|
||||||
properties: this.properties.map((prop) => prop.toJSON()),
|
properties: this.properties.map((prop) => prop.toJSON()),
|
||||||
typeParameters: this.typeParameters,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import type { ApiModel, ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
|||||||
import type { ReferenceData } from '~/model.server';
|
import type { ReferenceData } from '~/model.server';
|
||||||
import { resolveName, genReference, resolveDocComment, TokenDocumentation, genToken } from '~/util/parse.server';
|
import { resolveName, genReference, resolveDocComment, TokenDocumentation, genToken } from '~/util/parse.server';
|
||||||
|
|
||||||
|
export type DocItemConstructor<T = DocItem> = new (...args: any[]) => T;
|
||||||
|
|
||||||
export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
||||||
public readonly item: T;
|
public readonly item: T;
|
||||||
public readonly name: string;
|
public readonly name: string;
|
||||||
|
|||||||
@@ -1,33 +1,17 @@
|
|||||||
import type { ApiMethod, ApiModel } from '@microsoft/api-extractor-model';
|
import type { ApiMethod, ApiModel } from '@microsoft/api-extractor-model';
|
||||||
import { DocItem } from './DocItem';
|
import { DocFunction } from './DocFunction';
|
||||||
import { Visibility } from './Visibility';
|
import { Visibility } from './Visibility';
|
||||||
import {
|
|
||||||
type ParameterDocumentation,
|
|
||||||
type TokenDocumentation,
|
|
||||||
genParameter,
|
|
||||||
genToken,
|
|
||||||
generateTypeParamData,
|
|
||||||
TypeParameterData,
|
|
||||||
} from '~/util/parse.server';
|
|
||||||
|
|
||||||
export class DocMethod extends DocItem<ApiMethod> {
|
export class DocMethod extends DocFunction {
|
||||||
public readonly parameters: ParameterDocumentation[];
|
|
||||||
public readonly static: boolean;
|
public readonly static: boolean;
|
||||||
public readonly optional: boolean;
|
public readonly optional: boolean;
|
||||||
public readonly visibility: Visibility;
|
public readonly visibility: Visibility;
|
||||||
public readonly returnTypeTokens: TokenDocumentation[];
|
|
||||||
public readonly overloadIndex: number;
|
|
||||||
public readonly typeParameters: TypeParameterData[] = [];
|
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: ApiMethod) {
|
public constructor(model: ApiModel, item: ApiMethod) {
|
||||||
super(model, item);
|
super(model, item);
|
||||||
this.parameters = item.parameters.map((param) => genParameter(this.model, param));
|
|
||||||
this.static = item.isStatic;
|
this.static = item.isStatic;
|
||||||
this.optional = item.isOptional;
|
this.optional = item.isOptional;
|
||||||
this.visibility = item.isProtected ? Visibility.Protected : Visibility.Public;
|
this.visibility = item.isProtected ? Visibility.Protected : Visibility.Public;
|
||||||
this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
|
||||||
this.overloadIndex = item.overloadIndex;
|
|
||||||
this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override toJSON() {
|
public override toJSON() {
|
||||||
@@ -36,9 +20,6 @@ export class DocMethod extends DocItem<ApiMethod> {
|
|||||||
static: this.static,
|
static: this.static,
|
||||||
optional: this.optional,
|
optional: this.optional,
|
||||||
visibility: this.visibility,
|
visibility: this.visibility,
|
||||||
parameters: this.parameters,
|
|
||||||
returnTypeTokens: this.returnTypeTokens,
|
|
||||||
overloadIndex: this.overloadIndex,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,18 @@
|
|||||||
import type { ApiMethodSignature, ApiModel } from '@microsoft/api-extractor-model';
|
import type { ApiMethodSignature, ApiModel } from '@microsoft/api-extractor-model';
|
||||||
import { DocItem } from './DocItem';
|
import { DocFunction } from './DocFunction';
|
||||||
import {
|
|
||||||
type ParameterDocumentation,
|
|
||||||
type TokenDocumentation,
|
|
||||||
genParameter,
|
|
||||||
genToken,
|
|
||||||
generateTypeParamData,
|
|
||||||
type TypeParameterData,
|
|
||||||
} from '~/util/parse.server';
|
|
||||||
|
|
||||||
export class DocMethodSignature extends DocItem<ApiMethodSignature> {
|
export class DocMethodSignature extends DocFunction {
|
||||||
public readonly parameters: ParameterDocumentation[];
|
|
||||||
public readonly optional: boolean;
|
public readonly optional: boolean;
|
||||||
public readonly returnTypeTokens: TokenDocumentation[];
|
|
||||||
public readonly overloadIndex: number;
|
|
||||||
public readonly typeParameters: TypeParameterData[] = [];
|
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: ApiMethodSignature) {
|
public constructor(model: ApiModel, item: ApiMethodSignature) {
|
||||||
super(model, item);
|
super(model, item);
|
||||||
this.parameters = item.parameters.map((param) => genParameter(this.model, param));
|
|
||||||
this.optional = item.isOptional;
|
this.optional = item.isOptional;
|
||||||
this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
|
||||||
this.overloadIndex = item.overloadIndex;
|
|
||||||
this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override toJSON() {
|
public override toJSON() {
|
||||||
return {
|
return {
|
||||||
...super.toJSON(),
|
...super.toJSON(),
|
||||||
optional: this.optional,
|
optional: this.optional,
|
||||||
parameters: this.parameters,
|
|
||||||
returnTypeTokens: this.returnTypeTokens,
|
|
||||||
overloadIndex: this.overloadIndex,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
import type { ApiModel, ApiTypeAlias } from '@microsoft/api-extractor-model';
|
import type { ApiModel, ApiTypeAlias } from '@microsoft/api-extractor-model';
|
||||||
import { DocItem } from './DocItem';
|
import { DocItem } from './DocItem';
|
||||||
import { type TokenDocumentation, genToken, generateTypeParamData, type TypeParameterData } from '~/util/parse.server';
|
import { TypeParameterMixin } from './TypeParameterMixin';
|
||||||
|
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||||
|
|
||||||
export class DocTypeAlias extends DocItem<ApiTypeAlias> {
|
export class DocTypeAlias extends TypeParameterMixin(DocItem<ApiTypeAlias>) {
|
||||||
public readonly typeTokens: TokenDocumentation[];
|
public readonly typeTokens: TokenDocumentation[];
|
||||||
public readonly typeParameters: TypeParameterData[] = [];
|
|
||||||
|
|
||||||
public constructor(model: ApiModel, item: ApiTypeAlias) {
|
public constructor(model: ApiModel, item: ApiTypeAlias) {
|
||||||
super(model, item);
|
super(model, item);
|
||||||
this.typeTokens = item.typeExcerpt.spannedTokens.map((token) => genToken(model, token));
|
this.typeTokens = item.typeExcerpt.spannedTokens.map((token) => genToken(model, token));
|
||||||
this.typeParameters = item.typeParameters.map((typeParam) => generateTypeParamData(this.model, typeParam));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override toJSON() {
|
public override toJSON() {
|
||||||
return {
|
return {
|
||||||
...super.toJSON(),
|
...super.toJSON(),
|
||||||
typeTokens: this.typeTokens,
|
typeTokens: this.typeTokens,
|
||||||
typeParameters: this.typeParameters,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
packages/website/src/DocModel/TypeParameterMixin.ts
Normal file
24
packages/website/src/DocModel/TypeParameterMixin.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import type { ApiItem, ApiModel, ApiTypeParameterListMixin } from '@microsoft/api-extractor-model';
|
||||||
|
import type { DocItemConstructor } from './DocItem';
|
||||||
|
import { generateTypeParamData, TypeParameterData } from '~/util/parse.server';
|
||||||
|
|
||||||
|
export function TypeParameterMixin<TBase extends DocItemConstructor>(Base: TBase) {
|
||||||
|
return class Mixed extends Base {
|
||||||
|
public readonly typeParameters: TypeParameterData[] = [];
|
||||||
|
|
||||||
|
public constructor(...args: any[]);
|
||||||
|
public constructor(model: ApiModel, item: ApiItem) {
|
||||||
|
super(model, item);
|
||||||
|
this.typeParameters = (item as ApiTypeParameterListMixin).typeParameters.map((typeParam) =>
|
||||||
|
generateTypeParamData(this.model, typeParam),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override toJSON() {
|
||||||
|
return {
|
||||||
|
...super.toJSON(),
|
||||||
|
typeParameterData: this.typeParameters,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { VscSymbolClass, VscSymbolMethod, VscSymbolEnum, VscSymbolInterface, VscSymbolVariable } from 'react-icons/vsc';
|
|
||||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||||
import { vs } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
import { vs } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||||
import { TypeParamTable } from './TypeParamTable';
|
import { TypeParamTable } from './TypeParamTable';
|
||||||
|
import { generateIcon } from '~/util/icon';
|
||||||
import type { TypeParameterData } from '~/util/parse.server';
|
import type { TypeParameterData } from '~/util/parse.server';
|
||||||
|
|
||||||
export interface DocContainerProps {
|
export interface DocContainerProps {
|
||||||
@@ -13,27 +13,25 @@ export interface DocContainerProps {
|
|||||||
typeParams?: TypeParameterData[];
|
typeParams?: TypeParameterData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const symbolClass = 'mr-2';
|
|
||||||
const icons = {
|
|
||||||
Class: <VscSymbolClass color="blue" className={symbolClass} />,
|
|
||||||
Method: <VscSymbolMethod className={symbolClass} />,
|
|
||||||
Function: <VscSymbolMethod color="purple" className={symbolClass} />,
|
|
||||||
Enum: <VscSymbolEnum className={symbolClass} />,
|
|
||||||
Interface: <VscSymbolInterface color="blue" className={symbolClass} />,
|
|
||||||
TypeAlias: <VscSymbolVariable color="blue" className={symbolClass} />,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function DocContainer({ name, kind, excerpt, summary, typeParams, children }: DocContainerProps) {
|
export function DocContainer({ name, kind, excerpt, summary, typeParams, children }: DocContainerProps) {
|
||||||
return (
|
return (
|
||||||
<div className="px-10">
|
<div className="px-10">
|
||||||
<h1 style={{ fontFamily: 'JetBrains Mono' }} className="flex items-csenter content-center">
|
<h1 className="font-mono flex items-center content-center break-all">
|
||||||
{icons[kind as keyof typeof icons]}
|
{generateIcon(kind, 'mr-2')}
|
||||||
{name}
|
{name}
|
||||||
</h1>
|
</h1>
|
||||||
<h3>Code declaration:</h3>
|
<h3>Code declaration:</h3>
|
||||||
<SyntaxHighlighter language="typescript" style={vs} codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}>
|
<div>
|
||||||
{excerpt}
|
<SyntaxHighlighter
|
||||||
</SyntaxHighlighter>
|
wrapLines
|
||||||
|
wrapLongLines
|
||||||
|
language="typescript"
|
||||||
|
style={vs}
|
||||||
|
codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}
|
||||||
|
>
|
||||||
|
{excerpt}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
</div>
|
||||||
{typeParams?.length ? (
|
{typeParams?.length ? (
|
||||||
<>
|
<>
|
||||||
<h3>Type Parameters</h3>
|
<h3>Type Parameters</h3>
|
||||||
|
|||||||
45
packages/website/src/components/ItemSidebar.tsx
Normal file
45
packages/website/src/components/ItemSidebar.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { AiOutlineMenu } from 'react-icons/ai';
|
||||||
|
import { VscPackage } from 'react-icons/vsc';
|
||||||
|
import { generateIcon } from '~/util/icon';
|
||||||
|
import type { getMembers } from '~/util/parse.server';
|
||||||
|
|
||||||
|
export interface ItemListProps {
|
||||||
|
packageName: string;
|
||||||
|
data: {
|
||||||
|
members: ReturnType<typeof getMembers>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMenuClick() {
|
||||||
|
console.log('menu clicked');
|
||||||
|
// Todo show/hide list
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ItemSidebar({ packageName, data }: ItemListProps) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col max-h-full min-w-[270px] border-r-solid border-b-solid border-gray border-width-0.5">
|
||||||
|
<div className="flex justify-between content-center items-center border-b-solid border-gray border-width-0.5">
|
||||||
|
<h1 className="px-2 font-mono flex items-center content-center">
|
||||||
|
<VscPackage className="px-1" />
|
||||||
|
{`${packageName}`}
|
||||||
|
</h1>
|
||||||
|
<button className="lg:hidden mr-2 bg-transparent border-none" onClick={onMenuClick}>
|
||||||
|
<AiOutlineMenu size={32} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="hidden lg:block overflow-y-scroll overflow-x-clip p-7">
|
||||||
|
{data.members.map((member, i) => (
|
||||||
|
<div key={i} className="mb-1">
|
||||||
|
<a
|
||||||
|
className="flex content-center items-center align-center font-mono no-underline break-all color-blue-500"
|
||||||
|
href={member.path}
|
||||||
|
>
|
||||||
|
{generateIcon(member.kind, 'px-1')}
|
||||||
|
{member.name}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ export function Class({ data }: ClassProps) {
|
|||||||
kind={data.kind}
|
kind={data.kind}
|
||||||
excerpt={data.excerpt}
|
excerpt={data.excerpt}
|
||||||
summary={data.summary}
|
summary={data.summary}
|
||||||
typeParams={data.typeParameters}
|
typeParams={data.typeParameterData}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
{data.properties.length ? <PropertyList data={data.properties} /> : null}
|
{data.properties.length ? <PropertyList data={data.properties} /> : null}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function Function({ data }: FunctionProps) {
|
|||||||
kind={data.kind}
|
kind={data.kind}
|
||||||
excerpt={data.excerpt}
|
excerpt={data.excerpt}
|
||||||
summary={data.summary}
|
summary={data.summary}
|
||||||
typeParams={data.typeParameters}
|
typeParams={data.typeParameterData}
|
||||||
>
|
>
|
||||||
<ParameterTable data={data.parameters} />
|
<ParameterTable data={data.parameters} />
|
||||||
</DocContainer>
|
</DocContainer>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export function Interface({ data }: InterfaceProps) {
|
|||||||
kind={data.kind}
|
kind={data.kind}
|
||||||
excerpt={data.excerpt}
|
excerpt={data.excerpt}
|
||||||
summary={data.summary}
|
summary={data.summary}
|
||||||
typeParams={data.typeParameters}
|
typeParams={data.typeParameterData}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
{data.properties.length ? <PropertyList data={data.properties} /> : null}
|
{data.properties.length ? <PropertyList data={data.properties} /> : null}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export function TypeAlias({ data }: TypeAliasProps) {
|
|||||||
kind={data.kind}
|
kind={data.kind}
|
||||||
excerpt={data.excerpt}
|
excerpt={data.excerpt}
|
||||||
summary={data.summary}
|
summary={data.summary}
|
||||||
typeParams={data.typeParameters}
|
typeParams={data.typeParameterData}
|
||||||
>
|
>
|
||||||
<div>WIP</div>
|
<div>WIP</div>
|
||||||
</DocContainer>
|
</DocContainer>
|
||||||
|
|||||||
@@ -1,19 +1,32 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-throw-literal */
|
||||||
import { json } from '@remix-run/node';
|
import { json } from '@remix-run/node';
|
||||||
import { Params, useLoaderData } from '@remix-run/react';
|
import { Outlet, Params, useLoaderData, useParams } from '@remix-run/react';
|
||||||
|
import { ItemSidebar } from '~/components/ItemSidebar';
|
||||||
import { createApiModel } from '~/util/api-model.server';
|
import { createApiModel } from '~/util/api-model.server';
|
||||||
import { findPackage, getMembers } from '~/util/parse.server';
|
import { findPackage, getMembers } from '~/util/parse.server';
|
||||||
|
|
||||||
export async function loader({ params }: { params: Params }) {
|
export async function loader({ params }: { params: Params }) {
|
||||||
|
const UnknownResponse = new Response('Not Found', {
|
||||||
|
status: 404,
|
||||||
|
});
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://raw.githubusercontent.com/discordjs/docs/main/${params.packageName!}/${params.branchName!}.api.json`,
|
`https://raw.githubusercontent.com/discordjs/docs/main/${params.packageName!}/${params.branchName!}.api.json`,
|
||||||
);
|
);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
const data = await res.json();
|
const data = await res.json().catch(() => {
|
||||||
const model = createApiModel(data);
|
throw UnknownResponse;
|
||||||
|
});
|
||||||
|
|
||||||
|
const model = createApiModel(data);
|
||||||
const pkg = findPackage(model, params.packageName!);
|
const pkg = findPackage(model, params.packageName!);
|
||||||
|
|
||||||
|
if (!pkg) {
|
||||||
|
throw UnknownResponse;
|
||||||
|
}
|
||||||
|
|
||||||
return json({
|
return json({
|
||||||
members: getMembers(pkg!),
|
members: getMembers(pkg),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,14 +36,16 @@ interface LoaderData {
|
|||||||
|
|
||||||
export default function Package() {
|
export default function Package() {
|
||||||
const data = useLoaderData<LoaderData>();
|
const data = useLoaderData<LoaderData>();
|
||||||
|
const { packageName } = useParams();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul>
|
<div className="flex flex-col lg:flex-row overflow-none max-w-full h-full">
|
||||||
{data.members.map((member, i) => (
|
<div className="w-full lg:min-w-1/4 lg:max-w-1/4">
|
||||||
<li key={i}>
|
<ItemSidebar packageName={packageName!} data={data} />
|
||||||
<a href={member.path}>{member.name}</a>
|
</div>
|
||||||
</li>
|
<div>
|
||||||
))}
|
<Outlet />
|
||||||
</ul>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
14
packages/website/src/util/icon.tsx
Normal file
14
packages/website/src/util/icon.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { VscSymbolClass, VscSymbolMethod, VscSymbolEnum, VscSymbolInterface, VscSymbolVariable } from 'react-icons/vsc';
|
||||||
|
|
||||||
|
export function generateIcon(kind: string, className?: string) {
|
||||||
|
const icons = {
|
||||||
|
Class: <VscSymbolClass color="blue" className={className} />,
|
||||||
|
Method: <VscSymbolMethod className={className} />,
|
||||||
|
Function: <VscSymbolMethod color="purple" className={className} />,
|
||||||
|
Enum: <VscSymbolEnum className={className} />,
|
||||||
|
Interface: <VscSymbolInterface color="blue" className={className} />,
|
||||||
|
TypeAlias: <VscSymbolVariable color="blue" className={className} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
return icons[kind as keyof typeof icons];
|
||||||
|
}
|
||||||
@@ -165,6 +165,7 @@ export function genParameter(model: ApiModel, param: Parameter): ParameterDocume
|
|||||||
export function getMembers(pkg: ApiPackage) {
|
export function getMembers(pkg: ApiPackage) {
|
||||||
return pkg.members[0]!.members.map((member) => ({
|
return pkg.members[0]!.members.map((member) => ({
|
||||||
name: member.displayName,
|
name: member.displayName,
|
||||||
|
kind: member.kind,
|
||||||
path: generatePath(member.getHierarchy()),
|
path: generatePath(member.getHierarchy()),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
import { defineConfig } from 'unocss';
|
import { defineConfig } from 'unocss';
|
||||||
|
|
||||||
export default defineConfig({});
|
export default defineConfig({
|
||||||
|
theme: {
|
||||||
|
fontFamily: {
|
||||||
|
mono: ['JetBrains Mono'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user