Skip to content

Commit

Permalink
feat(docgen): typescript support
Browse files Browse the repository at this point in the history
  • Loading branch information
iCrawl committed Jun 8, 2022
1 parent 1afae90 commit 3279b40
Show file tree
Hide file tree
Showing 42 changed files with 955 additions and 321 deletions.
2 changes: 1 addition & 1 deletion packages/builders/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dist/
typings/

docs/**/*
!docs/index.yml
!docs/index.json
!docs/README.md

This comment was marked as spam.

Copy link
@scary3410

scary3410 Jun 8, 2022

comment left

!docs/examples/
!docs/examples/*.md
Expand Down
1 change: 1 addition & 0 deletions packages/builders/docs/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{ "name": "General", "files": [{ "name": "Welcome", "id": "welcome", "path": "../../README.md" }] }]
5 changes: 0 additions & 5 deletions packages/builders/docs/index.yml

This file was deleted.

4 changes: 2 additions & 2 deletions packages/builders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"build": "tsup",
"lint": "prettier --check . && eslint src __tests__ --ext mjs,js,ts",
"format": "prettier --write . && eslint src __tests__ --ext mjs,js,ts --fix",
"docs": "typedoc --json docs/typedoc-out.json src/index.ts && ts-docgen -i docs/typedoc-out.json -c docs/index.yml -o docs/docs.json",
"docs": "docgen -i src/index.ts -c docs/index.json -o docs/docs.json --typescript",
"prepublishOnly": "yarn build && yarn lint && yarn test",
"changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/builders/*'",
"release": "cliff-jumper"
Expand Down Expand Up @@ -60,6 +60,7 @@
"tslib": "^2.4.0"
},
"devDependencies": {
"@discordjs/docgen": "workspace:^",
"@discordjs/scripts": "workspace:^",
"@favware/cliff-jumper": "^1.8.3",
"@types/node": "^16.11.38",
Expand All @@ -71,7 +72,6 @@
"eslint-plugin-import": "^2.26.0",
"prettier": "^2.6.2",
"tsup": "^6.1.0",
"typedoc": "^0.22.17",
"typescript": "^4.7.3"
},
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion packages/collection/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pids
dist/
typings/
docs/**/*
!docs/index.yml
!docs/index.json
!docs/README.md

# Miscellaneous
Expand Down
1 change: 1 addition & 0 deletions packages/collection/docs/index.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{ "name": "General", "files": [{ "name": "Welcome", "id": "welcome", "path": "../../README.md" }] }]
5 changes: 0 additions & 5 deletions packages/collection/docs/index.yml

This file was deleted.

4 changes: 2 additions & 2 deletions packages/collection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"build": "tsup",
"lint": "prettier --check . && eslint src __tests__ --ext mjs,js,ts",
"format": "prettier --write . && eslint src __tests__ --ext mjs,js,ts --fix",
"docs": "typedoc --json docs/typedoc-out.json src/index.ts && ts-docgen -i docs/typedoc-out.json -c docs/index.yml -o docs/docs.json",
"docs": "docgen -i src/index.ts -c docs/index.json -o docs/docs.json --typescript",
"prepublishOnly": "yarn build && yarn lint && yarn test",
"changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/collection/*'",
"release": "cliff-jumper"
Expand Down Expand Up @@ -48,6 +48,7 @@
},
"homepage": "https://discord.js.org",
"devDependencies": {
"@discordjs/docgen": "workspace:^",
"@discordjs/scripts": "workspace:^",
"@favware/cliff-jumper": "^1.8.3",
"@types/node": "^16.11.38",
Expand All @@ -59,7 +60,6 @@
"eslint-plugin-import": "^2.26.0",
"prettier": "^2.6.2",
"tsup": "^6.1.0",
"typedoc": "^0.22.17",
"typescript": "^4.7.3"
},
"engines": {
Expand Down
5 changes: 3 additions & 2 deletions packages/docgen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@discordjs/collection": "workspace:^",
"@discordjs/collection": "^0.7.0",
"commander": "^9.3.0",
"jsdoc-to-markdown": "^7.1.1",
"tslib": "^2.4.0"
"tslib": "^2.4.0",
"typedoc": "^0.22.17"
},
"devDependencies": {
"@favware/cliff-jumper": "^1.8.3",
Expand Down
251 changes: 175 additions & 76 deletions packages/docgen/src/documentation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { join } from 'node:path';
import { dirname, join } from 'node:path';
import { Collection } from '@discordjs/collection';
import type { DeclarationReflection } from 'typedoc';
import type { ChildTypes, Class, Config, CustomDocs, RootTypes } from './interfaces/index.js';
import { DocumentedClass } from './types/class.js';
import { DocumentedConstructor } from './types/constructor.js';
Expand All @@ -23,101 +24,199 @@ export class Documentation {
public readonly externals = new Collection<string, DocumentedExternal>();

public constructor(
data: RootTypes[],
data: RootTypes[] | DeclarationReflection[],
private readonly config: Config,
private readonly custom?: Record<string, CustomDocs>,
) {
let items = data;
for (const item of items) {
switch (item.kind) {
case 'class': {
this.classes.set(item.name, new DocumentedClass(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
case 'function': {
if (item.scope === 'global' || !item.memberof) {
if (config.typescript) {
const items = data as DeclarationReflection[];

for (const item of items) {
switch (item.kindString) {
case 'Class': {
this.classes.set(item.name, new DocumentedClass(item, config));
if (item.children) {
this.parse(item.children, item.name);
}
break;
}

case 'Function': {
this.functions.set(item.name, new DocumentedMethod(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
break;
}
case 'interface': {
this.interfaces.set(item.name, new DocumentedInterface(item as unknown as Class, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
case 'typedef': {
this.typedefs.set(item.name, new DocumentedTypeDef(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;

case 'Interface':
case 'Type alias':
case 'Enumeration':
this.typedefs.set(item.name, new DocumentedTypeDef(item, config));
if (item.children) {
this.parse(item.children, item.name);
}
break;

default:
break;
}
case 'external': {
this.externals.set(item.name, new DocumentedExternal(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
} else {
let items = data as RootTypes[];

for (const item of items) {
switch (item.kind) {
case 'class': {
this.classes.set(item.name, new DocumentedClass(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
case 'function': {
if (item.scope === 'global' || !item.memberof) {
this.functions.set(item.name, new DocumentedMethod(item, config));
items = items.filter((i) => i.longname !== item.longname);
}
break;
}
case 'interface': {
this.interfaces.set(item.name, new DocumentedInterface(item as unknown as Class, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
case 'typedef': {
this.typedefs.set(item.name, new DocumentedTypeDef(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
case 'external': {
this.externals.set(item.name, new DocumentedExternal(item, config));
items = items.filter((i) => i.longname !== item.longname);
break;
}
default:
break;
}
default:
break;
}
}

this.parse(items as ChildTypes[]);
this.parse(items as ChildTypes[]);
}
}

public parse(items: ChildTypes[]) {
for (const member of items) {
let item: DocumentedMethod | DocumentedConstructor | DocumentedMember | DocumentedEvent | null = null;
public parse(items: ChildTypes[] | DeclarationReflection[], memberOf = '') {
if (this.config.typescript) {
const it = items as DeclarationReflection[];

switch (member.kind) {
case 'constructor': {
item = new DocumentedConstructor(member, this.config);
break;
}
case 'function': {
item = new DocumentedMethod(member, this.config);
break;
}
case 'member': {
item = new DocumentedMember(member, this.config);
break;
}
case 'event': {
item = new DocumentedEvent(member, this.config);
break;
for (const member of it) {
let item: DocumentedMethod | DocumentedConstructor | DocumentedMember | DocumentedEvent | null = null;

switch (member.kindString) {
case 'Constructor': {
item = new DocumentedConstructor(member, this.config);
break;
}
case 'Method': {
item = new DocumentedMethod(member, this.config);
break;
}
case 'Property': {
item = new DocumentedMember(member, this.config);
break;
}
case 'event': {
item = new DocumentedEvent(member, this.config);
break;
}
default: {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.warn(`- Unknown documentation kind "${member.kindString}" - \n${JSON.stringify(member)}\n`);
}
}
default: {
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.warn(`- Unknown documentation kind "${member.kind}" - \n${JSON.stringify(member)}\n`);

const parent = this.classes.get(memberOf) ?? this.interfaces.get(memberOf);
if (parent) {
if (item) {
parent.add(item);
} else {
console.warn(
`- Documentation item could not be constructed for "${member.name}" - \n${JSON.stringify(member)}\n`,
);
}
continue;
}

const info = [];
const name = (member.name || item?.data.name) ?? 'UNKNOWN';
const meta =
member.kindString === 'constructor'
? null
: {
file: member.sources?.[0]?.fileName,
line: member.sources?.[0]?.line,
path: dirname(member.sources?.[0]?.fileName ?? ''),
};

if (memberOf) info.push(`member of "${memberOf}"`);
if (meta) info.push(`${join(meta.path, meta.file ?? '')}${meta.line ? `:${meta.line}` : ''}`);

console.warn(`- "${name}"${info.length ? ` (${info.join(', ')})` : ''} has no accessible parent.`);
if (!name && !info.length) console.warn('Raw object:', member);
}
} else {
const it = items as ChildTypes[];

const parent = this.classes.get(member.memberof ?? '') ?? this.interfaces.get(member.memberof ?? '');
if (parent) {
if (item) {
parent.add(item);
} else {
console.warn(
`- Documentation item could not be constructed for "${member.name}" - \n${JSON.stringify(member)}\n`,
);
for (const member of it) {
let item: DocumentedMethod | DocumentedConstructor | DocumentedMember | DocumentedEvent | null = null;

switch (member.kind) {
case 'constructor': {
item = new DocumentedConstructor(member, this.config);
break;
}
case 'function': {
item = new DocumentedMethod(member, this.config);
break;
}
case 'member': {
item = new DocumentedMember(member, this.config);
break;
}
case 'event': {
item = new DocumentedEvent(member, this.config);
break;
}
default: {
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.warn(`- Unknown documentation kind "${member.kind}" - \n${JSON.stringify(member)}\n`);
}
}
continue;
}

const info = [];
const name = (member.name || item?.data.name) ?? 'UNKNOWN';
const memberof = member.memberof ?? item?.data.memberof;
const meta =
member.kind === 'constructor'
? null
: { file: member.meta.filename, line: member.meta.lineno, path: member.meta.path };
const parent = this.classes.get(member.memberof ?? '') ?? this.interfaces.get(member.memberof ?? '');
if (parent) {
if (item) {
parent.add(item);
} else {
console.warn(
`- Documentation item could not be constructed for "${member.name}" - \n${JSON.stringify(member)}\n`,
);
}
continue;
}

if (memberof) info.push(`member of "${memberof}"`);
if (meta) info.push(`${join(meta.path, meta.file)}${meta.line ? `:${meta.line}` : ''}`);
const info = [];
const name = (member.name || item?.data.name) ?? 'UNKNOWN';
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unnecessary-condition
const memberof = member.memberof ?? item?.data?.memberof;
const meta =
member.kind === 'constructor'
? null
: { file: member.meta.filename, line: member.meta.lineno, path: member.meta.path };

console.warn(`- "${name}"${info.length ? ` (${info.join(', ')})` : ''} has no accessible parent.`);
if (!name && !info.length) console.warn('Raw object:', member);
if (memberof) info.push(`member of "${memberof as string}"`);
if (meta) info.push(`${join(meta.path, meta.file)}${meta.line ? `:${meta.line}` : ''}`);

console.warn(`- "${name}"${info.length ? ` (${info.join(', ')})` : ''} has no accessible parent.`);
if (!name && !info.length) console.warn('Raw object:', member);
}
}
}

Expand Down
Loading

0 comments on commit 3279b40

Please sign in to comment.