mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 08:03:30 +01:00
feat: add website documentation early mvp (#8183)
Co-authored-by: iCrawl <buechler.noel@outlook.com>
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
**/CHANGELOG.md
|
||||
**/.turbo
|
||||
**/.yarn*
|
||||
**/dist/
|
||||
**/docs/**/*
|
||||
**/!docs/index.yml
|
||||
**/!docs/README.md
|
||||
**/coverage/
|
||||
**/LICENSE
|
||||
10
package.json
10
package.json
@@ -42,21 +42,21 @@
|
||||
"@commitlint/config-angular": "^17.0.0",
|
||||
"@favware/cliff-jumper": "^1.8.3",
|
||||
"@favware/npm-deprecate": "^1.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.28.0",
|
||||
"@typescript-eslint/parser": "^5.28.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"@typescript-eslint/parser": "^5.30.0",
|
||||
"c8": "^7.11.3",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"eslint": "^8.18.0",
|
||||
"eslint-config-marine": "^9.4.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^2.7.1",
|
||||
"eslint-import-resolver-typescript": "^3.1.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"husky": "^8.0.1",
|
||||
"is-ci": "^3.0.1",
|
||||
"prettier": "^2.7.1",
|
||||
"turbo": "^1.2.16",
|
||||
"turbo": "^1.3.1",
|
||||
"typescript": "^4.7.4",
|
||||
"vitest": "^0.15.1"
|
||||
"vitest": "^0.16.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
"@types/node": "^18.0.0",
|
||||
"dtslint": "^4.2.1",
|
||||
"eslint": "^8.18.0",
|
||||
"jest": "^28.1.1",
|
||||
"jest": "^28.1.2",
|
||||
"prettier": "^2.7.1",
|
||||
"tsd": "^0.21.0",
|
||||
"tslint": "^6.1.3",
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
"commander": "^9.3.0",
|
||||
"jsdoc-to-markdown": "^7.1.1",
|
||||
"tslib": "^2.4.0",
|
||||
"typedoc": "^0.23.0-beta.4"
|
||||
"typedoc": "^0.23.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@favware/cliff-jumper": "^1.8.3",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"@microsoft/api-extractor": "^7.28.2",
|
||||
"@types/jest": "^28.1.2",
|
||||
"eslint": "^8.18.0",
|
||||
"jest": "^28.1.1",
|
||||
"jest": "^28.1.2",
|
||||
"jest-websocket-mock": "^2.3.0",
|
||||
"mock-socket": "^9.1.5",
|
||||
"prettier": "^2.7.1",
|
||||
|
||||
@@ -9,3 +9,5 @@ coverage/
|
||||
tsup.config.*.mjs
|
||||
.cache
|
||||
build/
|
||||
src/styles/unocss.css
|
||||
api/
|
||||
|
||||
@@ -46,44 +46,49 @@
|
||||
},
|
||||
"homepage": "https://discord.js.org",
|
||||
"dependencies": {
|
||||
"@remix-run/node": "^1.6.0",
|
||||
"@remix-run/react": "^1.6.0",
|
||||
"@remix-run/serve": "^1.6.0",
|
||||
"@remix-run/server-runtime": "^1.6.0",
|
||||
"@remix-run/vercel": "^1.6.0",
|
||||
"@microsoft/api-extractor-model": "^7.21.0",
|
||||
"@microsoft/tsdoc": "^0.14.1",
|
||||
"@remix-run/node": "^1.6.3",
|
||||
"@remix-run/react": "^1.6.3",
|
||||
"@remix-run/serve": "^1.6.3",
|
||||
"@remix-run/server-runtime": "^1.6.3",
|
||||
"@remix-run/vercel": "^1.6.3",
|
||||
"@vscode/codicons": "^0.0.31",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"remix": "^1.6.0"
|
||||
"react-icons": "^4.4.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"remix": "^1.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@remix-run/dev": "^1.6.0",
|
||||
"@remix-run/dev": "^1.6.3",
|
||||
"@testing-library/cypress": "^8.0.3",
|
||||
"@testing-library/dom": "^8.13.0",
|
||||
"@testing-library/dom": "^8.14.0",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
"@testing-library/user-event": "^14.2.1",
|
||||
"@types/node": "^16.11.41",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.29.0",
|
||||
"@typescript-eslint/parser": "^5.29.0",
|
||||
"@unocss/cli": "^0.39.3",
|
||||
"@types/react-syntax-highlighter": "^15.5.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"@typescript-eslint/parser": "^5.30.0",
|
||||
"@unocss/cli": "^0.42.0",
|
||||
"@vitejs/plugin-react": "^1.3.2",
|
||||
"c8": "^7.11.3",
|
||||
"concurrently": "^7.2.2",
|
||||
"cypress": "^10.1.0",
|
||||
"cypress": "^10.3.0",
|
||||
"eslint": "^8.18.0",
|
||||
"eslint-config-marine": "^9.4.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^2.7.1",
|
||||
"eslint-import-resolver-typescript": "^3.1.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-react": "^7.30.0",
|
||||
"eslint-plugin-react": "^7.30.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"happy-dom": "^5.3.1",
|
||||
"msw": "^0.42.1",
|
||||
"happy-dom": "^5.3.4",
|
||||
"msw": "^0.42.3",
|
||||
"prettier": "^2.7.1",
|
||||
"typedoc": "^0.22.17",
|
||||
"typescript": "^4.7.4",
|
||||
"unocss": "^0.39.3"
|
||||
"unocss": "^0.42.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
|
||||
52
packages/website/src/DocModel/DocClass.ts
Normal file
52
packages/website/src/DocModel/DocClass.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
type ApiClass,
|
||||
type ApiModel,
|
||||
ApiItemKind,
|
||||
type ApiMethod,
|
||||
type ApiPropertyItem,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { DocMethod } from './DocMethod';
|
||||
import { DocProperty } from './DocProperty';
|
||||
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocClass extends DocItem<ApiClass> {
|
||||
public readonly extendsTokens: TokenDocumentation[] | null;
|
||||
public readonly implementsTokens: TokenDocumentation[][];
|
||||
public readonly methods: DocMethod[] = [];
|
||||
public readonly properties: DocProperty[] = [];
|
||||
|
||||
public constructor(model: ApiModel, item: ApiClass) {
|
||||
super(model, item);
|
||||
const extendsExcerpt = item.extendsType?.excerpt;
|
||||
this.extendsTokens = extendsExcerpt
|
||||
? extendsExcerpt.spannedTokens.map((token) => genToken(this.model, token))
|
||||
: null;
|
||||
this.implementsTokens = item.implementsTypes.map((excerpt) =>
|
||||
excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)),
|
||||
);
|
||||
|
||||
for (const member of item.members) {
|
||||
switch (member.kind) {
|
||||
case ApiItemKind.Method:
|
||||
this.methods.push(new DocMethod(this.model, member as ApiMethod));
|
||||
break;
|
||||
case ApiItemKind.Property:
|
||||
this.properties.push(new DocProperty(this.model, member as ApiPropertyItem));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
extendsTokens: this.extendsTokens,
|
||||
implementsTokens: this.implementsTokens,
|
||||
methods: this.methods.map((method) => method.toJSON()),
|
||||
properties: this.properties.map((prop) => prop.toJSON()),
|
||||
};
|
||||
}
|
||||
}
|
||||
25
packages/website/src/DocModel/DocEnum.ts
Normal file
25
packages/website/src/DocModel/DocEnum.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { ApiEnum, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
|
||||
export interface EnumMemberData {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export class DocEnum extends DocItem<ApiEnum> {
|
||||
public readonly members: EnumMemberData[] = [];
|
||||
|
||||
public constructor(model: ApiModel, item: ApiEnum) {
|
||||
super(model, item);
|
||||
|
||||
this.members = item.members.map((member) => ({
|
||||
name: member.name,
|
||||
}));
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
members: this.members,
|
||||
};
|
||||
}
|
||||
}
|
||||
25
packages/website/src/DocModel/DocFunction.ts
Normal file
25
packages/website/src/DocModel/DocFunction.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { ApiFunction, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { type ParameterDocumentation, type TokenDocumentation, genParameter, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocFunction extends DocItem<ApiFunction> {
|
||||
public readonly parameters: ParameterDocumentation[];
|
||||
public readonly returnTypeTokens: TokenDocumentation[];
|
||||
public readonly overloadIndex: number;
|
||||
|
||||
public constructor(model: ApiModel, item: ApiFunction) {
|
||||
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.overloadIndex = item.overloadIndex;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
parameters: this.parameters,
|
||||
returnTypeTokens: this.returnTypeTokens,
|
||||
overloadIndex: this.overloadIndex,
|
||||
};
|
||||
}
|
||||
}
|
||||
41
packages/website/src/DocModel/DocInterface.ts
Normal file
41
packages/website/src/DocModel/DocInterface.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { DocItem } from './DocItem';
|
||||
import { DocMethodSignature } from './DocMethodSignature';
|
||||
import { DocProperty } from './DocProperty';
|
||||
import { ApiInterface, ApiItemKind, ApiMethodSignature, ApiModel, ApiPropertySignature } from '~/api-extractor.server';
|
||||
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocInterface extends DocItem<ApiInterface> {
|
||||
public readonly extendsTokens: TokenDocumentation[][] | null;
|
||||
public readonly methods: DocMethodSignature[] = [];
|
||||
public readonly properties: DocProperty[] = [];
|
||||
|
||||
public constructor(model: ApiModel, item: ApiInterface) {
|
||||
super(model, item);
|
||||
|
||||
this.extendsTokens = item.extendsTypes.map((excerpt) =>
|
||||
excerpt.excerpt.spannedTokens.map((token) => genToken(this.model, token)),
|
||||
);
|
||||
|
||||
for (const member of item.members) {
|
||||
switch (member.kind) {
|
||||
case ApiItemKind.MethodSignature:
|
||||
this.methods.push(new DocMethodSignature(this.model, member as ApiMethodSignature));
|
||||
break;
|
||||
case ApiItemKind.PropertySignature:
|
||||
this.properties.push(new DocProperty(this.model, member as ApiPropertySignature));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
extendsTokens: this.extendsTokens,
|
||||
methods: this.methods.map((method) => method.toJSON()),
|
||||
properties: this.properties.map((prop) => prop.toJSON()),
|
||||
};
|
||||
}
|
||||
}
|
||||
36
packages/website/src/DocModel/DocItem.ts
Normal file
36
packages/website/src/DocModel/DocItem.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { ApiModel, ApiDeclaredItem } from '@microsoft/api-extractor-model';
|
||||
import type { ReferenceData } from '~/model.server';
|
||||
import { resolveName, genReference, resolveDocComment, TokenDocumentation, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocItem<T extends ApiDeclaredItem = ApiDeclaredItem> {
|
||||
public readonly item: T;
|
||||
public readonly name: string;
|
||||
public readonly referenceData: ReferenceData;
|
||||
public readonly summary: string | null;
|
||||
public readonly model: ApiModel;
|
||||
public readonly excerpt: string;
|
||||
public readonly excerptTokens: TokenDocumentation[] = [];
|
||||
public readonly kind: string;
|
||||
|
||||
public constructor(model: ApiModel, item: T) {
|
||||
this.item = item;
|
||||
this.kind = item.kind;
|
||||
this.model = model;
|
||||
this.name = resolveName(item);
|
||||
this.referenceData = genReference(item);
|
||||
this.summary = resolveDocComment(item);
|
||||
this.excerpt = item.excerpt.text;
|
||||
this.excerptTokens = item.excerpt.spannedTokens.map((token) => genToken(model, token));
|
||||
}
|
||||
|
||||
public toJSON() {
|
||||
return {
|
||||
name: this.name,
|
||||
referenceData: this.referenceData,
|
||||
summary: this.summary,
|
||||
excerpt: this.excerpt,
|
||||
excerptTokens: this.excerptTokens,
|
||||
kind: this.kind,
|
||||
};
|
||||
}
|
||||
}
|
||||
35
packages/website/src/DocModel/DocMethod.ts
Normal file
35
packages/website/src/DocModel/DocMethod.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { ApiMethod, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { Visibility } from './Visibility';
|
||||
import { type ParameterDocumentation, type TokenDocumentation, genParameter, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocMethod extends DocItem<ApiMethod> {
|
||||
public readonly parameters: ParameterDocumentation[];
|
||||
public readonly static: boolean;
|
||||
public readonly optional: boolean;
|
||||
public readonly visibility: Visibility;
|
||||
public readonly returnTypeTokens: TokenDocumentation[];
|
||||
public readonly overloadIndex: number;
|
||||
|
||||
public constructor(model: ApiModel, item: ApiMethod) {
|
||||
super(model, item);
|
||||
this.parameters = item.parameters.map((param) => genParameter(this.model, param));
|
||||
this.static = item.isStatic;
|
||||
this.optional = item.isOptional;
|
||||
this.visibility = item.isProtected ? Visibility.Protected : Visibility.Public;
|
||||
this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
||||
this.overloadIndex = item.overloadIndex;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
static: this.static,
|
||||
optional: this.optional,
|
||||
visibility: this.visibility,
|
||||
parameters: this.parameters,
|
||||
returnTypeTokens: this.returnTypeTokens,
|
||||
overloadIndex: this.overloadIndex,
|
||||
};
|
||||
}
|
||||
}
|
||||
28
packages/website/src/DocModel/DocMethodSignature.ts
Normal file
28
packages/website/src/DocModel/DocMethodSignature.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { ApiMethodSignature, ApiModel } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { type ParameterDocumentation, type TokenDocumentation, genParameter, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocMethodSignature extends DocItem<ApiMethodSignature> {
|
||||
public readonly parameters: ParameterDocumentation[];
|
||||
public readonly optional: boolean;
|
||||
public readonly returnTypeTokens: TokenDocumentation[];
|
||||
public readonly overloadIndex: number;
|
||||
|
||||
public constructor(model: ApiModel, item: ApiMethodSignature) {
|
||||
super(model, item);
|
||||
this.parameters = item.parameters.map((param) => genParameter(this.model, param));
|
||||
this.optional = item.isOptional;
|
||||
this.returnTypeTokens = item.returnTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
||||
this.overloadIndex = item.overloadIndex;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
optional: this.optional,
|
||||
parameters: this.parameters,
|
||||
returnTypeTokens: this.returnTypeTokens,
|
||||
overloadIndex: this.overloadIndex,
|
||||
};
|
||||
}
|
||||
}
|
||||
25
packages/website/src/DocModel/DocProperty.ts
Normal file
25
packages/website/src/DocModel/DocProperty.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { ApiPropertyItem, ApiModel, ApiPropertySignature } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocProperty extends DocItem<ApiPropertyItem> {
|
||||
public readonly propertyTypeTokens: TokenDocumentation[];
|
||||
public readonly readonly: boolean;
|
||||
public readonly optional: boolean;
|
||||
|
||||
public constructor(model: ApiModel, item: ApiPropertyItem | ApiPropertySignature) {
|
||||
super(model, item);
|
||||
this.propertyTypeTokens = item.propertyTypeExcerpt.spannedTokens.map((token) => genToken(this.model, token));
|
||||
this.readonly = item.isReadonly;
|
||||
this.optional = item.isOptional;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
propertyTypeTokens: this.propertyTypeTokens,
|
||||
readonly: this.readonly,
|
||||
optional: this.optional,
|
||||
};
|
||||
}
|
||||
}
|
||||
19
packages/website/src/DocModel/DocTypeAlias.ts
Normal file
19
packages/website/src/DocModel/DocTypeAlias.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { ApiModel, ApiTypeAlias } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { type TokenDocumentation, genToken } from '~/util/parse.server';
|
||||
|
||||
export class DocTypeAlias extends DocItem<ApiTypeAlias> {
|
||||
public readonly typeTokens: TokenDocumentation[];
|
||||
|
||||
public constructor(model: ApiModel, item: ApiTypeAlias) {
|
||||
super(model, item);
|
||||
this.typeTokens = item.typeExcerpt.spannedTokens.map((token) => genToken(model, token));
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
typeTokens: this.typeTokens,
|
||||
};
|
||||
}
|
||||
}
|
||||
22
packages/website/src/DocModel/DocVariable.ts
Normal file
22
packages/website/src/DocModel/DocVariable.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { ApiModel, ApiVariable } from '@microsoft/api-extractor-model';
|
||||
import { DocItem } from './DocItem';
|
||||
import { genToken, TokenDocumentation } from '~/util/parse.server';
|
||||
|
||||
export class DocVariable extends DocItem<ApiVariable> {
|
||||
public readonly typeTokens: TokenDocumentation[] = [];
|
||||
public readonly readonly: boolean;
|
||||
|
||||
public constructor(model: ApiModel, item: ApiVariable) {
|
||||
super(model, item);
|
||||
this.typeTokens = item.variableTypeExcerpt.spannedTokens.map((token) => genToken(model, token));
|
||||
this.readonly = item.isReadonly;
|
||||
}
|
||||
|
||||
public override toJSON() {
|
||||
return {
|
||||
...super.toJSON(),
|
||||
typeTokens: this.typeTokens,
|
||||
readonly: this.readonly,
|
||||
};
|
||||
}
|
||||
}
|
||||
4
packages/website/src/DocModel/Visibility.ts
Normal file
4
packages/website/src/DocModel/Visibility.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export enum Visibility {
|
||||
Public,
|
||||
Protected,
|
||||
}
|
||||
1
packages/website/src/api-extractor.server.ts
Normal file
1
packages/website/src/api-extractor.server.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@microsoft/api-extractor-model';
|
||||
39
packages/website/src/components/DocContainer.tsx
Normal file
39
packages/website/src/components/DocContainer.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { VscSymbolClass, VscSymbolMethod, VscSymbolEnum, VscSymbolInterface, VscSymbolVariable } from 'react-icons/vsc';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { vs } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
||||
|
||||
export interface DocContainerProps {
|
||||
name: string;
|
||||
kind: string;
|
||||
excerpt: string;
|
||||
summary?: string | null;
|
||||
children?: JSX.Element;
|
||||
}
|
||||
|
||||
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, children }: DocContainerProps) {
|
||||
return (
|
||||
<div className="px-10">
|
||||
<h1 style={{ fontFamily: 'JetBrains Mono' }} className="flex items-csenter content-center">
|
||||
{icons[kind as keyof typeof icons]}
|
||||
{name}
|
||||
</h1>
|
||||
<h3>Code declaration:</h3>
|
||||
<SyntaxHighlighter language="typescript" style={vs} codeTagProps={{ style: { fontFamily: 'JetBrains Mono' } }}>
|
||||
{excerpt}
|
||||
</SyntaxHighlighter>
|
||||
<h3>Summary</h3>
|
||||
<p>{summary ?? 'No summary provided.'}</p>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
19
packages/website/src/components/MethodList.tsx
Normal file
19
packages/website/src/components/MethodList.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { DocMethod } from '~/DocModel/DocMethod';
|
||||
import type { DocMethodSignature } from '~/DocModel/DocMethodSignature';
|
||||
|
||||
export interface MethodListProps {
|
||||
data: (ReturnType<DocMethod['toJSON']> | ReturnType<DocMethodSignature['toJSON']>)[];
|
||||
}
|
||||
|
||||
export function MethodList({ data }: MethodListProps) {
|
||||
return (
|
||||
<div>
|
||||
<h3>Methods</h3>
|
||||
<ul>
|
||||
{data.map((method) => (
|
||||
<li key={method.name}>{method.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
35
packages/website/src/components/ParameterTable.tsx
Normal file
35
packages/website/src/components/ParameterTable.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { constructHyperlinkedText } from '../util/util';
|
||||
import type { ParameterDocumentation } from '~/util/parse.server';
|
||||
|
||||
interface ParameterDetailProps {
|
||||
data: ParameterDocumentation[];
|
||||
}
|
||||
|
||||
export function ParameterTable({ data }: ParameterDetailProps) {
|
||||
return (
|
||||
<div className="p-10 border border-gray-200 solid rounded-md">
|
||||
<table className="w-full text-sm text-left text-black-500 dark:text-gray-400">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Optional</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((parameter) => (
|
||||
<tr key={parameter.name} className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
||||
<th className="py-4 font-normal text-gray-900 dark:text-white whitespace-nowrap">{parameter.name}</th>
|
||||
<th>
|
||||
<code>{constructHyperlinkedText(parameter.tokens)}</code>
|
||||
</th>
|
||||
<th>{parameter.isOptional ? 'Yes' : 'No'}</th>
|
||||
<th>None</th>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
18
packages/website/src/components/PropertyList.tsx
Normal file
18
packages/website/src/components/PropertyList.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import type { DocProperty } from '~/DocModel/DocProperty';
|
||||
|
||||
export interface PropertyListProps {
|
||||
data: ReturnType<DocProperty['toJSON']>[];
|
||||
}
|
||||
|
||||
export function PropertyList({ data }: PropertyListProps) {
|
||||
return (
|
||||
<div>
|
||||
<h3>Properties</h3>
|
||||
<ul>
|
||||
{data.map((prop) => (
|
||||
<li key={prop.name}>{prop.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
19
packages/website/src/components/model/Class.tsx
Normal file
19
packages/website/src/components/model/Class.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DocContainer } from '../DocContainer';
|
||||
import { MethodList } from '../MethodList';
|
||||
import { PropertyList } from '../PropertyList';
|
||||
import type { DocClass } from '~/DocModel/DocClass';
|
||||
|
||||
export interface ClassProps {
|
||||
data: ReturnType<DocClass['toJSON']>;
|
||||
}
|
||||
|
||||
export function Class({ data }: ClassProps) {
|
||||
return (
|
||||
<DocContainer name={data.name} kind={data.kind} excerpt={data.excerpt} summary={data.summary}>
|
||||
<>
|
||||
{data.properties.length ? <PropertyList data={data.properties} /> : null}
|
||||
{data.methods.length ? <MethodList data={data.methods} /> : null}
|
||||
</>
|
||||
</DocContainer>
|
||||
);
|
||||
}
|
||||
21
packages/website/src/components/model/Enum.tsx
Normal file
21
packages/website/src/components/model/Enum.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { DocContainer } from '../DocContainer';
|
||||
import type { DocEnum } from '~/DocModel/DocEnum';
|
||||
|
||||
export interface EnumProps {
|
||||
data: ReturnType<DocEnum['toJSON']>;
|
||||
}
|
||||
|
||||
export function Enum({ data }: EnumProps) {
|
||||
return (
|
||||
<DocContainer name={data.name} kind={data.kind} excerpt={data.excerpt} summary={data.summary}>
|
||||
<>
|
||||
<h3>Members</h3>
|
||||
<ul>
|
||||
{data.members.map((member) => (
|
||||
<li key={member.name}>{member.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
</DocContainer>
|
||||
);
|
||||
}
|
||||
15
packages/website/src/components/model/Function.tsx
Normal file
15
packages/website/src/components/model/Function.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { DocContainer } from '../DocContainer';
|
||||
import { ParameterTable } from '../ParameterTable';
|
||||
import type { DocFunction } from '~/DocModel/DocFunction';
|
||||
|
||||
export interface FunctionProps {
|
||||
data: ReturnType<DocFunction['toJSON']>;
|
||||
}
|
||||
|
||||
export function Function({ data }: FunctionProps) {
|
||||
return (
|
||||
<DocContainer name={data.name} kind={data.kind} excerpt={data.excerpt} summary={data.summary}>
|
||||
<ParameterTable data={data.parameters} />
|
||||
</DocContainer>
|
||||
);
|
||||
}
|
||||
19
packages/website/src/components/model/Interface.tsx
Normal file
19
packages/website/src/components/model/Interface.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DocContainer } from '../DocContainer';
|
||||
import { MethodList } from '../MethodList';
|
||||
import { PropertyList } from '../PropertyList';
|
||||
import type { DocInterface } from '~/DocModel/DocInterface';
|
||||
|
||||
export interface InterfaceProps {
|
||||
data: ReturnType<DocInterface['toJSON']>;
|
||||
}
|
||||
|
||||
export function Interface({ data }: InterfaceProps) {
|
||||
return (
|
||||
<DocContainer name={data.name} kind={data.kind} excerpt={data.excerpt} summary={data.summary}>
|
||||
<>
|
||||
{data.properties.length ? <PropertyList data={data.properties} /> : null}
|
||||
{data.methods.length ? <MethodList data={data.methods} /> : null}
|
||||
</>
|
||||
</DocContainer>
|
||||
);
|
||||
}
|
||||
14
packages/website/src/components/model/TypeAlias.tsx
Normal file
14
packages/website/src/components/model/TypeAlias.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { DocContainer } from '../DocContainer';
|
||||
import type { DocTypeAlias } from '~/DocModel/DocTypeAlias';
|
||||
|
||||
export interface TypeAliasProps {
|
||||
data: ReturnType<DocTypeAlias['toJSON']>;
|
||||
}
|
||||
|
||||
export function TypeAlias({ data }: TypeAliasProps) {
|
||||
return (
|
||||
<DocContainer name={data.name} kind={data.kind} excerpt={data.excerpt} summary={data.summary}>
|
||||
<div>WIP</div>
|
||||
</DocContainer>
|
||||
);
|
||||
}
|
||||
10
packages/website/src/components/model/Variable.tsx
Normal file
10
packages/website/src/components/model/Variable.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { DocContainer } from '../DocContainer';
|
||||
import type { DocVariable } from '~/DocModel/DocVariable';
|
||||
|
||||
export interface VariableProps {
|
||||
data: ReturnType<DocVariable['toJSON']>;
|
||||
}
|
||||
|
||||
export function Variable({ data }: VariableProps) {
|
||||
return <DocContainer name={data.name} kind={data.kind} excerpt={data.excerpt} summary={data.summary} />;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RemixBrowser } from '@remix-run/react';
|
||||
import { hydrate } from 'react-dom';
|
||||
import { hydrateRoot } from 'react-dom/client';
|
||||
|
||||
hydrate(<RemixBrowser />, document);
|
||||
hydrateRoot(document, <RemixBrowser />);
|
||||
|
||||
67
packages/website/src/model.server.ts
Normal file
67
packages/website/src/model.server.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import {
|
||||
ApiClass,
|
||||
ApiDeclaredItem,
|
||||
ApiEntryPoint,
|
||||
ApiEnum,
|
||||
ApiFunction,
|
||||
ApiInterface,
|
||||
ApiItemKind,
|
||||
ApiModel,
|
||||
ApiTypeAlias,
|
||||
ApiVariable,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import '@microsoft/tsdoc/schemas/tsdoc.schema.json'; // Try to work around vercel issue
|
||||
import { DocClass } from './DocModel/DocClass';
|
||||
import { DocEnum } from './DocModel/DocEnum';
|
||||
import { DocFunction } from './DocModel/DocFunction';
|
||||
import { DocInterface } from './DocModel/DocInterface';
|
||||
import { DocItem } from './DocModel/DocItem';
|
||||
import { DocTypeAlias } from './DocModel/DocTypeAlias';
|
||||
import { DocVariable } from './DocModel/DocVariable';
|
||||
import { findPackage } from './util/parse.server';
|
||||
|
||||
export interface ReferenceData {
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export function findMember(model: ApiModel, packageName: string, memberName: string): DocItem | undefined {
|
||||
const pkg = findPackage(model, packageName)!;
|
||||
const member = (pkg.members[0] as ApiEntryPoint).findMembersByName(memberName)[0];
|
||||
|
||||
if (!(member instanceof ApiDeclaredItem)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
switch (member.kind) {
|
||||
case ApiItemKind.Class:
|
||||
return new DocClass(model, member as ApiClass);
|
||||
case ApiItemKind.Function:
|
||||
return new DocFunction(model, member as ApiFunction);
|
||||
case ApiItemKind.Interface:
|
||||
return new DocInterface(model, member as ApiInterface);
|
||||
case ApiItemKind.TypeAlias:
|
||||
return new DocTypeAlias(model, member as ApiTypeAlias);
|
||||
case ApiItemKind.Variable:
|
||||
return new DocVariable(model, member as ApiVariable);
|
||||
case ApiItemKind.Enum:
|
||||
return new DocEnum(model, member as ApiEnum);
|
||||
default:
|
||||
return new DocItem(model, member);
|
||||
}
|
||||
|
||||
// return {
|
||||
// name: resolveName(member),
|
||||
// kind: member.kind,
|
||||
// summary: resolveDocComment(member),
|
||||
// excerpt: member.excerpt.text,
|
||||
// tokens: member.excerpt.spannedTokens.map((token) => genToken(model, token)),
|
||||
// refs: [...findReferences(model, member.excerpt).values()].map(genReference),
|
||||
// members: getProperties(member).map((member) => ({
|
||||
// tokens: member.excerpt.spannedTokens.map((token) => genToken(model, token)),
|
||||
// summary: resolveDocComment(member),
|
||||
// })),
|
||||
// parameters: member instanceof ApiFunction ? member.parameters.map((param) => genParameter(model, param)) : [],
|
||||
// foo: excerpt.spannedTokens.map((token) => genToken(model, token)),
|
||||
// };
|
||||
}
|
||||
3
packages/website/src/routes/docs/$branchName/index.tsx
Normal file
3
packages/website/src/routes/docs/$branchName/index.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function BranchesLanding() {
|
||||
return <div>Branches</div>;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { json } from '@remix-run/node';
|
||||
import { Params, useLoaderData } from '@remix-run/react';
|
||||
import type { DocClass } from '~/DocModel/DocClass';
|
||||
import type { DocEnum } from '~/DocModel/DocEnum';
|
||||
import type { DocFunction } from '~/DocModel/DocFunction';
|
||||
import type { DocInterface } from '~/DocModel/DocInterface';
|
||||
import type { DocTypeAlias } from '~/DocModel/DocTypeAlias';
|
||||
import type { DocVariable } from '~/DocModel/DocVariable';
|
||||
import { ApiItem, ApiModel, ApiPackage } from '~/api-extractor.server';
|
||||
import { Class } from '~/components/model/Class';
|
||||
import { Enum } from '~/components/model/Enum';
|
||||
import { Function } from '~/components/model/Function';
|
||||
import { Interface } from '~/components/model/Interface';
|
||||
import { TypeAlias } from '~/components/model/TypeAlias';
|
||||
import { Variable } from '~/components/model/Variable';
|
||||
import { findMember } from '~/model.server';
|
||||
import { TSDocConfiguration } from '~/tsdoc.server';
|
||||
|
||||
export async function loader({ params }: { params: Params }) {
|
||||
const res = await fetch(
|
||||
`https://raw.githubusercontent.com/discordjs/docs/main/${params.packageName!}/${params.branchName!}.api.json`,
|
||||
);
|
||||
const data = await res.json();
|
||||
|
||||
const model = new ApiModel();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
const apiPackage = ApiItem.deserialize(data, {
|
||||
apiJsonFilename: '',
|
||||
toolPackage: data.metadata.toolPackage,
|
||||
toolVersion: data.metadata.toolVersion,
|
||||
versionToDeserialize: data.metadata.schemaVersion,
|
||||
tsdocConfiguration: new TSDocConfiguration(),
|
||||
}) as ApiPackage;
|
||||
model.addMember(apiPackage);
|
||||
return json(findMember(model, params.packageName!, params.memberName!)?.toJSON());
|
||||
}
|
||||
|
||||
export default function Member() {
|
||||
const data = useLoaderData();
|
||||
|
||||
switch (data.kind) {
|
||||
case 'Class':
|
||||
return <Class data={data as ReturnType<DocClass['toJSON']>} />;
|
||||
case 'Function':
|
||||
return <Function data={data as ReturnType<DocFunction['toJSON']>} />;
|
||||
case 'Interface':
|
||||
return <Interface data={data as ReturnType<DocInterface['toJSON']>} />;
|
||||
case 'TypeAlias':
|
||||
return <TypeAlias data={data as ReturnType<DocTypeAlias['toJSON']>} />;
|
||||
case 'Variable':
|
||||
return <Variable data={data as ReturnType<DocVariable['toJSON']>} />;
|
||||
case 'Enum':
|
||||
return <Enum data={data as ReturnType<DocEnum['toJSON']>} />;
|
||||
default:
|
||||
return <div>Cannot render that item type</div>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { json } from '@remix-run/node';
|
||||
import { Params, useLoaderData } from '@remix-run/react';
|
||||
import { ApiItem, ApiModel, ApiPackage } from '~/api-extractor.server';
|
||||
import { TSDocConfiguration } from '~/tsdoc.server';
|
||||
import { findPackage, getMembers } from '~/util/parse.server';
|
||||
|
||||
export async function loader({ params }: { params: Params }) {
|
||||
const res = await fetch(
|
||||
`https://raw.githubusercontent.com/discordjs/docs/main/${params.packageName!}/${params.branchName!}.api.json`,
|
||||
);
|
||||
const data = await res.json();
|
||||
|
||||
const model = new ApiModel();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
const apiPackage = ApiItem.deserialize(data, {
|
||||
apiJsonFilename: '',
|
||||
toolPackage: data.metadata.toolPackage,
|
||||
toolVersion: data.metadata.toolVersion,
|
||||
versionToDeserialize: data.metadata.schemaVersion,
|
||||
tsdocConfiguration: new TSDocConfiguration(),
|
||||
}) as ApiPackage;
|
||||
model.addMember(apiPackage);
|
||||
|
||||
const pkg = findPackage(model, params.packageName!);
|
||||
return json({
|
||||
members: getMembers(pkg!),
|
||||
});
|
||||
}
|
||||
|
||||
interface LoaderData {
|
||||
members: ReturnType<typeof getMembers>;
|
||||
}
|
||||
|
||||
export default function Package() {
|
||||
const data = useLoaderData<LoaderData>();
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{data.members.map((member, i) => (
|
||||
<li key={i}>
|
||||
<a href={member.path}>{member.name}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
3
packages/website/src/routes/docs/index.tsx
Normal file
3
packages/website/src/routes/docs/index.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function DocsLanding() {
|
||||
return <div>Documentation</div>;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100vh;
|
||||
@@ -5,3 +7,11 @@ body {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial,
|
||||
Noto Sans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', Segoe UI Symbol, 'Noto Color Emoji';
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: 'JetBrains Mono';
|
||||
}
|
||||
|
||||
1
packages/website/src/tsdoc.server.tsx
Normal file
1
packages/website/src/tsdoc.server.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@microsoft/tsdoc';
|
||||
169
packages/website/src/util/parse.server.ts
Normal file
169
packages/website/src/util/parse.server.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
import {
|
||||
type ApiModel,
|
||||
type ApiPackage,
|
||||
type ApiItem,
|
||||
ApiItemKind,
|
||||
ApiDocumentedItem,
|
||||
type Excerpt,
|
||||
ExcerptTokenKind,
|
||||
ApiNameMixin,
|
||||
type ApiPropertyItem,
|
||||
type ExcerptToken,
|
||||
type Parameter,
|
||||
} from '@microsoft/api-extractor-model';
|
||||
import type { DocNode, DocParagraph, DocPlainText } from '@microsoft/tsdoc';
|
||||
|
||||
export function findPackage(model: ApiModel, name: string): ApiPackage | undefined {
|
||||
return (model.findMembersByName(name)[0] ?? model.findMembersByName(`@discordjs/${name}`)[0]) as
|
||||
| ApiPackage
|
||||
| undefined;
|
||||
}
|
||||
|
||||
function generatePath(items: readonly ApiItem[]) {
|
||||
let path = '/docs/main/packages/';
|
||||
for (const item of items) {
|
||||
switch (item.kind) {
|
||||
case ApiItemKind.Model:
|
||||
case ApiItemKind.EntryPoint:
|
||||
case ApiItemKind.EnumMember:
|
||||
break;
|
||||
case ApiItemKind.Package:
|
||||
path += `${item.displayName}/`;
|
||||
break;
|
||||
default:
|
||||
path += `${item.displayName}/`;
|
||||
}
|
||||
}
|
||||
|
||||
return path.replace(/@discordjs\//, '');
|
||||
}
|
||||
|
||||
export function resolveDocComment(item: ApiDocumentedItem) {
|
||||
if (!(item instanceof ApiDocumentedItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { tsdocComment } = item;
|
||||
|
||||
if (!tsdocComment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { summarySection } = tsdocComment;
|
||||
|
||||
function recurseNodes(nodes: readonly DocNode[] | undefined): string | null {
|
||||
if (!nodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const node of nodes) {
|
||||
switch (node.kind) {
|
||||
case 'Paragraph':
|
||||
return recurseNodes((node as DocParagraph).nodes);
|
||||
case 'PlainText':
|
||||
return (node as DocPlainText).text;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return recurseNodes(summarySection.nodes);
|
||||
}
|
||||
|
||||
export function findReferences(model: ApiModel, excerpt: Excerpt) {
|
||||
const retVal: Set<ApiItem> = new Set();
|
||||
|
||||
for (const token of excerpt.spannedTokens) {
|
||||
switch (token.kind) {
|
||||
case ExcerptTokenKind.Reference: {
|
||||
const item = model.resolveDeclarationReference(token.canonicalReference!, undefined).resolvedApiItem;
|
||||
if (!item) {
|
||||
break;
|
||||
}
|
||||
|
||||
retVal.add(item);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
export function resolveName(item: ApiItem) {
|
||||
if (ApiNameMixin.isBaseClassOf(item)) {
|
||||
return item.name;
|
||||
}
|
||||
|
||||
return item.displayName;
|
||||
}
|
||||
|
||||
export function getProperties(item: ApiItem) {
|
||||
const properties: ApiPropertyItem[] = [];
|
||||
for (const member of item.members) {
|
||||
switch (member.kind) {
|
||||
case ApiItemKind.Property:
|
||||
case ApiItemKind.PropertySignature:
|
||||
case ApiItemKind.Method:
|
||||
case ApiItemKind.MethodSignature:
|
||||
properties.push(member as ApiPropertyItem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
export interface TokenDocumentation {
|
||||
text: string;
|
||||
path: string | null;
|
||||
kind: string;
|
||||
}
|
||||
|
||||
export interface ParameterDocumentation {
|
||||
name: string;
|
||||
isOptional: boolean;
|
||||
tokens: TokenDocumentation[];
|
||||
}
|
||||
|
||||
export function genReference(item: ApiItem) {
|
||||
return {
|
||||
name: resolveName(item),
|
||||
path: generatePath(item.getHierarchy()),
|
||||
};
|
||||
}
|
||||
|
||||
export function genToken(model: ApiModel, token: ExcerptToken) {
|
||||
const item = token.canonicalReference
|
||||
? model.resolveDeclarationReference(token.canonicalReference, undefined).resolvedApiItem ?? null
|
||||
: null;
|
||||
|
||||
return {
|
||||
kind: token.kind,
|
||||
text: token.text,
|
||||
path: item ? generatePath(item.getHierarchy()) : null,
|
||||
};
|
||||
}
|
||||
|
||||
export function genParameter(model: ApiModel, param: Parameter): ParameterDocumentation {
|
||||
return {
|
||||
name: param.name,
|
||||
isOptional: param.isOptional,
|
||||
tokens: param.parameterTypeExcerpt.spannedTokens.map((token) => genToken(model, token)),
|
||||
};
|
||||
}
|
||||
|
||||
export function getMembers(pkg: ApiPackage) {
|
||||
return pkg.members[0]!.members.map((member) => ({
|
||||
name: member.displayName,
|
||||
path: generatePath(member.getHierarchy()),
|
||||
}));
|
||||
}
|
||||
23
packages/website/src/util/util.tsx
Normal file
23
packages/website/src/util/util.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { TokenDocumentation } from './parse.server';
|
||||
|
||||
/**
|
||||
* Constructs a hyperlinked html node based on token type references
|
||||
*
|
||||
* @param tokens An array of documentation tokens to construct the HTML
|
||||
*
|
||||
* @returns An array of JSX elements and string comprising the hyperlinked text
|
||||
*/
|
||||
export function constructHyperlinkedText(tokens: TokenDocumentation[]) {
|
||||
const html: (JSX.Element | string)[] = [];
|
||||
|
||||
for (const token of tokens) {
|
||||
if (token.path) {
|
||||
html.push(<a href={token.path}>{token.text}</a>);
|
||||
continue;
|
||||
}
|
||||
|
||||
html.push(token.text);
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
@@ -11,5 +11,5 @@
|
||||
"~/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "remix.env.d.ts", "types.d.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user