Skip to content
This repository was archived by the owner on Jun 8, 2022. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/documentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'path';
import type { JSONOutput } from 'typedoc';
import type { customSettings, ProjectData } from './index';
import { ClassDoc, parseClass } from './util/class';
import { NamespaceDoc, parseNamespace } from './util/namespace';
import { TypedefDoc, parseTypedef } from './util/typedef';
import { version } from '../package.json';

Expand All @@ -26,21 +27,24 @@ interface CodeDoc {
// interfaces: unknown[]
// external: unknown[]
typedefs: TypedefDoc[];
namespaces: NamespaceDoc[];
}

export function generateDocs(data: ProjectData): CodeDoc {
const classes = [];
const classes: ClassDoc[] = [];
// interfaces = [], // not using this at the moment
// externals = [], // ???
const typedefs = [];
const typedefs: TypedefDoc[] = [];
const namespaces: NamespaceDoc[] = [];

for (const c of data.children ?? []) {
const { type, value } = parseRootElement(c);
if (!value) continue;

if (type === 'class') classes.push(value);
// if (type == 'interface') interfaces.push(value)
if (type === 'typedef') typedefs.push(value);
// if (type === 'interface') interfaces.push(value);
if (type === 'typedef') typedefs.push(value as TypedefDoc);
if (type === 'namespace') namespaces.push(value);
// if (type == 'external') externals.push(value)
}

Expand All @@ -49,6 +53,7 @@ export function generateDocs(data: ProjectData): CodeDoc {
// interfaces,
// externals,
typedefs,
namespaces,
};
}

Expand All @@ -67,6 +72,11 @@ function parseRootElement(element: DeclarationReflection) {
type: 'typedef',
value: parseTypedef(element),
};
case 'Namespace':
return {
type: 'namespace',
value: parseNamespace(element),
};

// Externals?

Expand All @@ -91,4 +101,6 @@ export function parseMeta(element: DeclarationReflection): DocMeta | undefined {
path: path.dirname(meta.fileName),
};
}

return undefined;
}
87 changes: 50 additions & 37 deletions src/util/class.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import path from 'node:path';

import { DeclarationReflection, DocMeta, parseMeta } from '../documentation';
import { DocType, parseType, parseTypeSimple } from './types';

export interface ClassDoc {
name: string;
description?: string | undefined;
see?: string[] | undefined;
extends?: [string] | undefined;
implements?: [string] | undefined;
access?: 'private' | undefined;
abstract?: boolean | undefined;
deprecated?: boolean | undefined;
access?: 'private' | undefined;
construct?: ClassMethodDoc | undefined;
props?: ClassPropDoc[] | undefined;
methods?: ClassMethodDoc[] | undefined;
deprecated?: boolean | undefined;
description?: string | undefined;
events?: ClassEventDoc[] | undefined;
examples?: string[] | undefined;
extendedDescription?: string | undefined;
extends?: [string] | undefined;
implements?: [string] | undefined;
isExternal?: boolean | undefined;
meta?: DocMeta | undefined;
methods?: ClassMethodDoc[] | undefined;
name: string;
props?: ClassPropDoc[] | undefined;
see?: string[] | undefined;
}

export function parseClass(element: DeclarationReflection): ClassDoc {
const extended = element.extendedTypes?.[0];
const implemented = element.implementedTypes?.[0];
const examples = element.comment?.tags?.filter((t) => t.tag === 'example')?.map((t) => t.text.trim());

const construct = element.children?.find((c) => c.kindString === 'Constructor');
// Ignore setter-only accessors (the typings still exist, but the docs don't show them)
const props = element.children?.filter(
Expand All @@ -35,9 +39,11 @@ export function parseClass(element: DeclarationReflection): ClassDoc {
return {
name: element.name === 'default' ? path.parse(meta?.file ?? 'default').name : element.name,
description: element.comment?.shortText?.trim(),
extendedDescription: element.comment?.text?.trim(),
see: element.comment?.tags?.filter((t) => t.tag === 'see').map((t) => t.text.trim()),
extends: extended ? [parseTypeSimple(extended)] : undefined,
implements: implemented ? [parseTypeSimple(implemented)] : undefined,
examples: examples ? examples : undefined,
access:
element.flags.isPrivate || element.comment?.tags?.some((t) => t.tag === 'private' || t.tag === 'internal')
? 'private'
Expand All @@ -49,29 +55,32 @@ export function parseClass(element: DeclarationReflection): ClassDoc {
methods: methods && methods.length > 0 ? methods.map(parseClassMethod) : undefined,
events: events && events.length > 0 ? events.map(parseClassEvent) : undefined,
meta,
isExternal: element.flags.isExternal,
};
}

interface ClassPropDoc {
name: string;
description?: string | undefined;
see?: string[] | undefined;
scope?: 'static' | undefined;
access?: 'private' | undefined;
readonly?: boolean | undefined;
nullable?: never | undefined; // it would already be in the type
abstract?: boolean | undefined;
deprecated?: boolean | undefined;
access?: 'private' | undefined;
default?: string | boolean | number | undefined;
type?: DocType | undefined;
props?: never | undefined; // prefer using a type reference (like a dedicated instance) instead of documenting using @property tags
deprecated?: boolean | undefined;
description?: string | undefined;
extendedDescription?: string | undefined;
meta?: DocMeta | undefined;
name: string;
nullable?: never | undefined; // it would already be in the type
props?: never | undefined; // prefer using a type reference (like a dedicated instance) instead of documenting using @property tags
readonly?: boolean | undefined;
scope?: 'static' | undefined;
see?: string[] | undefined;
type?: DocType | undefined;
}

function parseClassProp(element: DeclarationReflection): ClassPropDoc {
const base: ClassPropDoc = {
name: element.name,
description: element.comment?.shortText?.trim(),
extendedDescription: element.comment?.text?.trim(),
see: element.comment?.tags?.filter((t) => t.tag === 'see').map((t) => t.text.trim()),
scope: element.flags.isStatic ? 'static' : undefined,
access:
Expand Down Expand Up @@ -108,6 +117,7 @@ function parseClassProp(element: DeclarationReflection): ClassPropDoc {
return {
...res,
description: getter.comment?.shortText?.trim(),
extendedDescription: getter.comment?.text?.trim(),
see: getter.comment?.tags?.filter((t) => t.tag === 'see').map((t) => t.text.trim()),
access:
getter.flags.isPrivate || getter.comment?.tags?.some((t) => t.tag === 'private' || t.tag === 'internal')
Expand All @@ -130,19 +140,20 @@ function parseClassProp(element: DeclarationReflection): ClassPropDoc {
}

interface ClassMethodDoc {
name: string;
description?: string | undefined;
see?: string[] | undefined;
scope?: 'static' | undefined;
access?: 'private' | undefined;
inherits?: never | undefined; // let's just don't
inherited?: never | undefined; // let's just don't
implements?: never | undefined; // let's just don't
examples?: string[] | undefined;
abstract?: boolean | undefined;
access?: 'private' | undefined;
async?: never | undefined; // it would already be in the type
deprecated?: boolean | undefined;
description?: string | undefined;
emits?: string[] | undefined;
throws?: never | undefined; // let's just don't
examples?: string[] | undefined;
extendDescription?: string | undefined;
generator?: never | undefined; // not used by djs
implements?: never | undefined; // let's just don't
inherited?: never | undefined; // let's just don't
inherits?: never | undefined; // let's just don't
meta?: DocMeta | undefined;
name: string;
params?:
| {
name: string;
Expand All @@ -154,11 +165,11 @@ interface ClassMethodDoc {
type?: DocType | undefined;
}[]
| undefined;
async?: never | undefined; // it would already be in the type
generator?: never | undefined; // not used by djs
returns?: DocType | undefined;
returnsDescription?: string | undefined;
meta?: DocMeta | undefined;
scope?: 'static' | undefined;
see?: string[] | undefined;
throws?: never | undefined; // let's just don't
}

export function parseClassMethod(element: DeclarationReflection): ClassMethodDoc {
Expand All @@ -167,6 +178,7 @@ export function parseClassMethod(element: DeclarationReflection): ClassMethodDoc
return {
name: element.name,
description: signature.comment?.shortText?.trim(),
extendDescription: signature.comment?.text?.trim(),
see: signature.comment?.tags?.filter((t) => t.tag === 'see').map((t) => t.text.trim()),
scope: element.flags.isStatic ? 'static' : undefined,
access:
Expand Down Expand Up @@ -201,10 +213,11 @@ export function parseParam(param: DeclarationReflection): ClassMethodParamDoc {
}

interface ClassEventDoc {
name: string;
description?: string | undefined;
see?: string[] | undefined;
deprecated?: boolean | undefined;
description?: string | undefined;
extendedDescription?: string | undefined;
meta?: DocMeta | undefined;
name: string;
params?:
| {
name: string;
Expand All @@ -216,7 +229,7 @@ interface ClassEventDoc {
type?: DocType | undefined;
}[]
| undefined;
meta?: DocMeta | undefined;
see?: string[] | undefined;
}

function parseClassEvent(element: DeclarationReflection): ClassEventDoc {
Expand Down
34 changes: 34 additions & 0 deletions src/util/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { DocMeta, parseMeta, type DeclarationReflection } from '../documentation';
import { parseTypedef, TypedefDoc } from './typedef';

export interface NamespaceDoc {
deprecated?: boolean | undefined;
description?: string | undefined;
enumerations?: TypedefDoc[] | undefined;
extendedDescription?: string | undefined;
interfaces?: TypedefDoc[] | undefined;
isExternal?: boolean | undefined;
meta?: DocMeta | undefined;
name: string;
see?: string[] | undefined;
typeAliases?: TypedefDoc[] | undefined;
}

export function parseNamespace(element: DeclarationReflection): NamespaceDoc {
const typeAliases = element.children?.filter((c) => c.kindString === 'Type alias');
const interfaces = element.children?.filter((c) => c.kindString === 'Interface');
const enumerations = element.children?.filter((c) => c.kindString === 'Enumeration');

return {
name: element.name,
description: element.comment?.shortText?.trim(),
extendedDescription: element.comment?.text?.trim(),
see: element.comment?.tags?.filter((t) => t.tag === 'see').map((t) => t.text.trim()),
deprecated: element.comment?.tags?.some((t) => t.tag === 'deprecated'),
typeAliases: typeAliases && typeAliases.length > 0 ? typeAliases.map(parseTypedef) : undefined,
interfaces: interfaces && interfaces.length > 0 ? interfaces.map(parseTypedef) : undefined,
enumerations: enumerations && enumerations.length > 0 ? enumerations.map(parseTypedef) : undefined,
meta: parseMeta(element),
isExternal: element.flags.isExternal,
};
}
30 changes: 24 additions & 6 deletions src/util/typedef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,39 @@ import type { ClassMethodParamDoc } from './class';
import { DocType, parseType, typeUtil } from './types';

export interface TypedefDoc {
name: string;
description?: string | undefined;
see?: string[] | undefined;
access?: 'private' | undefined;
deprecated?: boolean | undefined;
type?: DocType | undefined;
props?: ClassMethodParamDoc[] | undefined;
description?: string | undefined;
extendedDescription?: string | undefined;
isExternal?: boolean | undefined;
meta?: DocMeta | undefined;
name: string;
params?: ClassMethodParamDoc[] | undefined;
props?: ClassMethodParamDoc[] | undefined;
returns?: DocType | undefined;
returnsDescription?: string | undefined;
meta?: DocMeta | undefined;
see?: string[] | undefined;
type?: DocType | undefined;
variant: 'type' | 'interface' | 'enum';
}

function parseKindString(kindString: DeclarationReflection['kindString']): TypedefDoc['variant'] {
switch (kindString?.toLowerCase()) {
case 'interface':
return 'interface';
case 'enumeration':
return 'enum';
case 'type alias':
default:
return 'type';
}
}

export function parseTypedef(element: DeclarationReflection): TypedefDoc {
const baseReturn: TypedefDoc = {
name: element.name,
description: element.comment?.shortText?.trim(),
extendedDescription: element.comment?.text?.trim(),
see: element.comment?.tags?.filter((t) => t.tag === 'see').map((t) => t.text.trim()),
access:
element.flags.isPrivate || element.comment?.tags?.some((t) => t.tag === 'private' || t.tag === 'internal')
Expand All @@ -29,6 +45,8 @@ export function parseTypedef(element: DeclarationReflection): TypedefDoc {
// @ts-ignore
type: element.type ? parseType(element.type) : undefined,
meta: parseMeta(element),
variant: parseKindString(element.kindString),
isExternal: element.flags.isExternal,
};

let typeDef: DeclarationReflection | undefined;
Expand Down
10 changes: 9 additions & 1 deletion tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@ export const tsup: Options = {
dts: true,
entryPoints: ['src/index.ts'],
format: ['esm', 'cjs'],
minify: true,
minify: false,
keepNames: true,
skipNodeModulesBundle: true,
sourcemap: true,
target: 'es2021',
esbuildOptions: (options, context) => {
if (context.format === 'cjs') {
options.banner = {
js: '"use strict";',
};
}
},
};