UNPKG

kompendium

Version:

Documentation generator for Stencil components

290 lines (248 loc) 7.68 kB
import { Application, Decorator, Reflection, ReflectionKind, DeclarationReflection, TypeDocAndTSOptions, } from 'typedoc'; import { CommentTag, ParameterReflection, SignatureReflection, } from 'typedoc/dist/lib/models'; import { JsonDocsTag, JsonDocsProp, JsonDocsMethodReturn, } from '@stencil/core/internal'; import negate from 'lodash/negate'; import { InterfaceDescription, AliasDescription, EnumDescription, EnumMember, TypeDescription, MethodDescription, ParameterDescription, ClassDescription, } from '../types'; import { existsSync } from 'fs'; interface MethodSignature { parameters: ParameterDescription[]; returns: JsonDocsMethodReturn; } export function parseFile(filename: string): TypeDescription[] { if (!existsSync(filename)) { // eslint-disable-next-line no-console console.warn('typeRoot file does not exist', filename); return []; } const app = new Application(); const options: Partial<TypeDocAndTSOptions> = { readme: 'none', ignoreCompilerErrors: true, }; if (filename.endsWith('.d.ts')) { options.includeDeclarations = true; options.exclude = ['**/+(*test*|node_modules)/**']; } app.bootstrap(options); const reflection = app.convert([filename]); if (!reflection) { // eslint-disable-next-line no-console console.warn('Could not find any type information'); return []; } const data: TypeDescription[] = []; reflection.traverse(traverseCallback(data)); return data; } const fns = { [ReflectionKind.Interface]: addInterface, [ReflectionKind.Class]: addClass, [ReflectionKind.CallSignature]: addSignature, [ReflectionKind.Parameter]: addParam, [ReflectionKind.TypeAlias]: addType, // [ReflectionKind.TypeLiteral]: addType, [ReflectionKind.Enum]: addEnum, [ReflectionKind.EnumMember]: addEnumMember, }; const traverseCallback = (data: any) => (reflection: Reflection) => { const fn = fns[reflection.kind]; if (fn) { fn(reflection, data); } else { reflection.traverse(traverseCallback(data)); } }; function addInterface( reflection: DeclarationReflection, data: InterfaceDescription[], ) { if (!reflection.flags.isExported) { return; } data.push({ type: 'interface', name: reflection.name, typeParams: getTypeParams(reflection), docs: getDocs(reflection), docsTags: getDocsTags(reflection), props: reflection.children.filter(isProperty).map(getProperty), methods: reflection.children.filter(isMethod).map(getMethod), sources: getSources(reflection), }); } function addClass(reflection: DeclarationReflection, data: ClassDescription[]) { if (!reflection.flags.isExported) { return; } data.push({ type: 'class', name: reflection.name, typeParams: getTypeParams(reflection), docs: getDocs(reflection), docsTags: getDocsTags(reflection), props: reflection.children?.filter(isProperty).map(getProperty), methods: reflection.children?.filter(isMethod).map(getMethod), sources: getSources(reflection), decorators: reflection.decorators?.map(getDecorator), }); } function addSignature(reflection: SignatureReflection, data: MethodSignature) { if (Array.isArray(data)) { return; } data.parameters = []; data.returns = { type: reflection.type.toString(), docs: reflection.parent.parent.comment?.tags?.find(isReturns)?.text || '', }; reflection.traverse(traverseCallback(data)); } function addParam(reflection: ParameterReflection, data: MethodSignature) { data.parameters.push({ name: reflection.name, type: reflection.type.toString(), docs: reflection.parent.parent.parent.comment?.tags ?.filter(isParam) .find((tag) => tag.paramName === reflection.name) ?.text.trim() || '', default: reflection.defaultValue, optional: reflection.flags.isOptional, }); } function addType(reflection: DeclarationReflection, data: AliasDescription[]) { if (!reflection.flags.isExported) { return; } data.push({ type: 'alias', name: reflection.name, docs: getDocs(reflection), docsTags: getDocsTags(reflection), alias: reflection.type.toString(), sources: getSources(reflection), }); } function addEnum(reflection: DeclarationReflection, data: EnumDescription[]) { if (!reflection.flags.isExported) { return; } const members = []; reflection.traverse(traverseCallback(members)); data.push({ type: 'enum', name: reflection.name, docs: getDocs(reflection), docsTags: getDocsTags(reflection), members: members, sources: getSources(reflection), }); } function addEnumMember(reflection: DeclarationReflection, data: EnumMember[]) { data.push({ name: reflection.name, docs: getDocs(reflection), docsTags: getDocsTags(reflection), value: reflection.defaultValue, }); } function getDocs(reflection: Reflection): string { return [reflection.comment?.shortText, reflection.comment?.text] .join('\n') .trim(); } function getDocsTags(reflection: DeclarationReflection) { return reflection.comment?.tags?.map(getTag) || []; } function getTag(tag: CommentTag): JsonDocsTag { return { name: tag.tagName, text: tag.text.trim(), }; } function isProperty(reflection: DeclarationReflection): boolean { return ( reflection.kind === ReflectionKind.Property && reflection.type.toString() !== 'function' ); } function isMethod(reflection: DeclarationReflection): boolean { return ( reflection.kind === ReflectionKind.Property && reflection.type.toString() === 'function' ); } function isParam(tag: CommentTag): boolean { return tag.tagName === 'param'; } function isReturns(tag: CommentTag): boolean { return tag.tagName === 'returns'; } function getProperty(reflection: DeclarationReflection): Partial<JsonDocsProp> { return { name: reflection.name, type: reflection.type.toString(), docs: getDocs(reflection), docsTags: getDocsTags(reflection), default: reflection.defaultValue, optional: reflection.flags.isOptional, }; } function getMethod(reflection: DeclarationReflection): MethodDescription { const signature = getSignature(reflection); return { name: reflection.name, docs: getDocs(reflection), docsTags: reflection.comment?.tags ?.filter(negate(isParam)) .filter(negate(isReturns)) .map(getTag), ...signature, }; } function getSignature(reflection: Reflection): MethodSignature { const signature: Partial<MethodSignature> = {}; reflection.traverse(traverseCallback(signature)); return signature as MethodSignature; } function getTypeParams(reflection: DeclarationReflection) { return ( reflection.typeParameters?.map((param) => ({ name: param.name, })) || [] ); } function getSources(reflection: DeclarationReflection) { return reflection.sources.map((source) => source.file.fullFileName); } function getDecorator(decorator: Decorator) { return { name: decorator.name, arguments: decorator.arguments, }; }