mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs: improve docs generation for namespaces (#64747)
Improves docs epxerience for interfaces / type aliases that are merged with a namespace. PR Close #64747
This commit is contained in:
parent
96388b6d8a
commit
59635bba34
18 changed files with 174 additions and 64 deletions
|
|
@ -14,32 +14,32 @@ import {
|
|||
ComponentRef,
|
||||
createComponent,
|
||||
DestroyRef,
|
||||
effect,
|
||||
ElementRef,
|
||||
EnvironmentInjector,
|
||||
inject,
|
||||
Injector,
|
||||
input,
|
||||
output,
|
||||
PendingTasks,
|
||||
PLATFORM_ID,
|
||||
Type,
|
||||
ViewContainerRef,
|
||||
ViewEncapsulation,
|
||||
PendingTasks,
|
||||
output,
|
||||
input,
|
||||
effect,
|
||||
} from '@angular/core';
|
||||
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';
|
||||
import {TOC_SKIP_CONTENT_MARKER, NavigationState} from '../../../services';
|
||||
import {TableOfContents} from '../../table-of-contents/table-of-contents.component';
|
||||
import {IconComponent} from '../../icon/icon.component';
|
||||
import {handleHrefClickEventWithRouter} from '../../../utils';
|
||||
import {Snippet} from '../../../interfaces';
|
||||
import {Router} from '@angular/router';
|
||||
import {fromEvent} from 'rxjs';
|
||||
import {Snippet} from '../../../interfaces';
|
||||
import {NavigationState, TOC_SKIP_CONTENT_MARKER} from '../../../services';
|
||||
import {handleHrefClickEventWithRouter} from '../../../utils';
|
||||
import {IconComponent} from '../../icon/icon.component';
|
||||
import {TableOfContents} from '../../table-of-contents/table-of-contents.component';
|
||||
|
||||
import {DomSanitizer} from '@angular/platform-browser';
|
||||
import {Breadcrumb} from '../../breadcrumb/breadcrumb.component';
|
||||
import {CopySourceCodeButton} from '../../copy-source-code-button/copy-source-code-button.component';
|
||||
import {ExampleViewer} from '../example-viewer/example-viewer.component';
|
||||
import {DomSanitizer} from '@angular/platform-browser';
|
||||
|
||||
const TOC_HOST_ELEMENT_NAME = 'docs-table-of-contents';
|
||||
export const ASSETS_EXAMPLES_PATH = 'assets/content/examples';
|
||||
|
|
@ -253,7 +253,9 @@ export class DocViewer {
|
|||
// the code
|
||||
private loadCopySourceCodeButtons(): void {
|
||||
const staticCodeSnippets = <Element[]>(
|
||||
Array.from(this.elementRef.nativeElement.querySelectorAll('.docs-code:not([mermaid])'))
|
||||
Array.from(
|
||||
this.elementRef.nativeElement.querySelectorAll('.docs-code:not([mermaid],.docs-no-copy)'),
|
||||
)
|
||||
);
|
||||
|
||||
for (let codeSnippet of staticCodeSnippets) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ export enum MemberType {
|
|||
Getter = 'getter',
|
||||
Setter = 'setter',
|
||||
EnumItem = 'enum_item',
|
||||
Interface = 'interface',
|
||||
TypeAlias = 'type_alias',
|
||||
}
|
||||
|
||||
export enum DecoratorType {
|
||||
|
|
@ -96,7 +98,7 @@ export interface ConstantEntry extends DocEntry {
|
|||
/** Documentation entity for a type alias. */
|
||||
export interface TypeAliasEntry extends ConstantEntry {
|
||||
generics: GenericEntry[];
|
||||
members?: MemberEntry[]; // For merged namespaces
|
||||
members: MemberEntry[]; // For merged namespaces
|
||||
}
|
||||
|
||||
/** Documentation entity for a TypeScript class. */
|
||||
|
|
@ -192,6 +194,12 @@ export interface PropertyEntry extends MemberEntry {
|
|||
/** Sub-entry for a class method. */
|
||||
export type MethodEntry = MemberEntry & FunctionEntry;
|
||||
|
||||
/** Sub-entry for an interface (included via namespace). */
|
||||
export type InterfaceMemberEntry = MemberEntry & InterfaceEntry;
|
||||
|
||||
/** Sub-entry for a type alias (included via namespace). */
|
||||
export type TypeAliasMemberEntry = MemberEntry & TypeAliasEntry;
|
||||
|
||||
/** Sub-entry for a single function parameter. */
|
||||
export interface ParameterEntry {
|
||||
name: string;
|
||||
|
|
|
|||
|
|
@ -84,10 +84,13 @@ export function isEnumEntry(entry: DocEntry): entry is EnumEntry {
|
|||
}
|
||||
|
||||
/** Gets whether the given entry represents an interface. */
|
||||
export function isInterfaceEntry(
|
||||
entry: MemberEntryRenderable,
|
||||
): entry is InterfaceEntryRenderable & MemberEntryRenderable;
|
||||
export function isInterfaceEntry(entry: DocEntryRenderable): entry is InterfaceEntryRenderable;
|
||||
export function isInterfaceEntry(entry: DocEntry): entry is InterfaceEntry;
|
||||
export function isInterfaceEntry(entry: DocEntry): entry is InterfaceEntry {
|
||||
return entry.entryType === EntryType.Interface;
|
||||
export function isInterfaceEntry(entry: DocEntry | MemberEntryRenderable): entry is InterfaceEntry {
|
||||
return (entry as DocEntry).entryType === EntryType.Interface;
|
||||
}
|
||||
|
||||
/** Gets whether the given member entry is a method entry. */
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export type ConstantEntryRenderable = ConstantEntry &
|
|||
export type TypeAliasEntryRenderable = TypeAliasEntry &
|
||||
DocEntryRenderable &
|
||||
HasRenderableToc & {
|
||||
members?: MemberEntryRenderable[];
|
||||
members: MemberEntryRenderable[];
|
||||
};
|
||||
|
||||
/** Documentation entity for a TypeScript class augmented transformed content for rendering. */
|
||||
|
|
@ -108,6 +108,7 @@ export interface MemberEntryRenderable extends MemberEntry {
|
|||
jsdocTags: JsDocTagRenderable[];
|
||||
deprecationMessage: string | null;
|
||||
htmlUsageNotes: string;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
/** Sub-entry for a class method augmented transformed content for rendering. */
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
*/
|
||||
|
||||
import {Fragment, h} from 'preact';
|
||||
import {MemberType} from '../entities.mjs';
|
||||
import {
|
||||
isClassMethodEntry,
|
||||
isGetterEntry,
|
||||
isInterfaceEntry,
|
||||
isPropertyEntry,
|
||||
isSetterEntry,
|
||||
} from '../entities/categorization.mjs';
|
||||
|
|
@ -23,6 +25,7 @@ import {
|
|||
import {getFunctionMetadataRenderable} from '../transforms/function-transforms.mjs';
|
||||
import {ClassMethodInfo} from './class-method-info';
|
||||
import {CodeSymbol} from './code-symbols';
|
||||
import {CodeTableOfContents} from './code-table-of-contents';
|
||||
import {DeprecatedLabel} from './deprecated-label';
|
||||
import {RawHtml} from './raw-html';
|
||||
|
||||
|
|
@ -53,11 +56,12 @@ export function ClassMember(props: {member: MemberEntryRenderable}) {
|
|||
);
|
||||
|
||||
const memberName = member.name;
|
||||
const displayName = member.displayName;
|
||||
const returnType = getMemberType(member);
|
||||
return (
|
||||
<div id={memberName} className={REFERENCE_MEMBER_CARD}>
|
||||
<header className={REFERENCE_MEMBER_CARD_HEADER}>
|
||||
<h3>{memberName}</h3>
|
||||
<h3>{displayName ?? memberName}</h3>
|
||||
{isClassMethodEntry(member) && member.signatures.length > 1 ? (
|
||||
<span>{member.signatures.length} overloads</span>
|
||||
) : returnType ? (
|
||||
|
|
@ -67,6 +71,11 @@ export function ClassMember(props: {member: MemberEntryRenderable}) {
|
|||
)}
|
||||
</header>
|
||||
{body}
|
||||
{isInterfaceEntry(member) ? (
|
||||
<CodeTableOfContents entry={member} hideCopyButton={true} embedded={true} />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -76,6 +85,10 @@ function getMemberType(entry: MemberEntryRenderable): string | null {
|
|||
return entry.implementation.returnType;
|
||||
} else if (isPropertyEntry(entry) || isGetterEntry(entry) || isSetterEntry(entry)) {
|
||||
return entry.type;
|
||||
} else if (entry.memberType === MemberType.TypeAlias) {
|
||||
return 'type';
|
||||
} else if (entry.memberType === MemberType.Interface) {
|
||||
return 'interface';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,14 @@
|
|||
|
||||
import {h} from 'preact';
|
||||
import {renderToString} from 'preact-render-to-string';
|
||||
import {CodeLineGroup} from './code-line-group';
|
||||
import {HasRenderableToc} from '../entities/traits.mjs';
|
||||
import {CodeLineGroup} from './code-line-group';
|
||||
|
||||
export function CodeTableOfContents(props: {entry: HasRenderableToc}) {
|
||||
export function CodeTableOfContents(props: {
|
||||
entry: HasRenderableToc;
|
||||
hideCopyButton?: boolean;
|
||||
embedded?: boolean;
|
||||
}) {
|
||||
let html: string;
|
||||
// Prefer the formatted code if available
|
||||
if (props.entry.formattedCode) {
|
||||
|
|
@ -26,5 +30,14 @@ export function CodeTableOfContents(props: {entry: HasRenderableToc}) {
|
|||
${props.entry.afterCodeGroups}`;
|
||||
}
|
||||
|
||||
return <div class="docs-code" dangerouslySetInnerHTML={{__html: html}}></div>;
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
(props.hideCopyButton ? 'docs-no-copy' : '') +
|
||||
(props.embedded ? ' embedded' : '') +
|
||||
' docs-code'
|
||||
}
|
||||
dangerouslySetInnerHTML={{__html: html}}
|
||||
></div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export async function getClassRenderable(
|
|||
): Promise<ClassEntryRenderable> {
|
||||
return setEntryFlags(
|
||||
await addRenderableCodeToc(
|
||||
addRenderableMembers(
|
||||
await addRenderableMembers(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(
|
||||
|
|
@ -36,6 +36,7 @@ export async function getClassRenderable(
|
|||
),
|
||||
),
|
||||
),
|
||||
classEntry.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
DecoratorEntry,
|
||||
DocEntry,
|
||||
EntryType,
|
||||
FunctionSignatureMetadata,
|
||||
GenericEntry,
|
||||
MemberEntry,
|
||||
DecoratorEntry,
|
||||
MemberTags,
|
||||
ParameterEntry,
|
||||
PropertyEntry,
|
||||
|
|
@ -34,16 +34,20 @@ import {
|
|||
} from '../entities/categorization.mjs';
|
||||
import {CodeLineRenderable} from '../entities/renderables.mjs';
|
||||
import {HasModuleName, HasRenderableToc} from '../entities/traits.mjs';
|
||||
import {getSymbolUrl} from '../symbol-context.mjs';
|
||||
import {
|
||||
getHighlighterInstance,
|
||||
insertParenthesesForDecoratorInShikiHtml,
|
||||
replaceKeywordFromShikiHtml,
|
||||
} from '../shiki/shiki.mjs';
|
||||
import {getSymbolUrl} from '../symbol-context.mjs';
|
||||
|
||||
import {filterLifecycleMethods, mergeGettersAndSetters} from './member-transforms.mjs';
|
||||
import {formatJs} from './format-code.mjs';
|
||||
import {codeToHtml} from '../../../shared/shiki.mjs';
|
||||
import {formatJs} from './format-code.mjs';
|
||||
import {
|
||||
filterLifecycleMethods,
|
||||
filterMergedNamespaceMembers,
|
||||
mergeGettersAndSetters,
|
||||
} from './member-transforms.mjs';
|
||||
|
||||
const INDENT = ' ';
|
||||
const SPACE = ' ';
|
||||
|
|
@ -198,7 +202,10 @@ function mapDocEntryToCode(entry: DocEntry): CodeTableOfContentsData {
|
|||
}
|
||||
|
||||
if (isInterfaceEntry(entry)) {
|
||||
return getCodeTocData(mergeGettersAndSetters(entry.members), isDeprecated);
|
||||
return getCodeTocData(
|
||||
filterMergedNamespaceMembers(mergeGettersAndSetters(entry.members)),
|
||||
isDeprecated,
|
||||
);
|
||||
}
|
||||
|
||||
if (isFunctionEntry(entry)) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import {
|
|||
addHtmlUsageNotes,
|
||||
setEntryFlags,
|
||||
} from './jsdoc-transforms.mjs';
|
||||
import {addRenderableMembers} from './member-transforms.mjs';
|
||||
import {addModuleName} from './module-name.mjs';
|
||||
import {addRepo} from './repo.mjs';
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export async function getEnumRenderable(
|
|||
): Promise<EnumEntryRenderable> {
|
||||
return setEntryFlags(
|
||||
await addRenderableCodeToc(
|
||||
addRenderableMembers(
|
||||
await addRenderableMembers(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(
|
||||
|
|
@ -36,6 +36,7 @@ export async function getEnumRenderable(
|
|||
),
|
||||
),
|
||||
),
|
||||
classEntry.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export async function getInterfaceRenderable(
|
|||
): Promise<InterfaceEntryRenderable> {
|
||||
return setEntryFlags(
|
||||
await addRenderableCodeToc(
|
||||
addRenderableMembers(
|
||||
await addRenderableMembers(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(
|
||||
|
|
@ -36,6 +36,7 @@ export async function getInterfaceRenderable(
|
|||
),
|
||||
),
|
||||
),
|
||||
entry.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,24 +15,24 @@ import {
|
|||
HasDeprecatedFlag,
|
||||
HasDescription,
|
||||
HasDeveloperPreviewFlag,
|
||||
hasExperimentalFlag,
|
||||
HasHtmlDescription,
|
||||
HasHtmlUsageNotes,
|
||||
HasJsDocTags,
|
||||
HasModuleName,
|
||||
HasRenderableJsDocTags,
|
||||
hasExperimentalFlag,
|
||||
HasStableFlag,
|
||||
} from '../entities/traits.mjs';
|
||||
|
||||
import {addApiLinksToHtml} from './code-transforms.mjs';
|
||||
import {parseMarkdown} from '../../../shared/marked/parse.mjs';
|
||||
import {getHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
import {
|
||||
getCurrentSymbol,
|
||||
getSymbols,
|
||||
getSymbolUrl,
|
||||
unknownSymbolMessage,
|
||||
} from '../symbol-context.mjs';
|
||||
import {parseMarkdown} from '../../../shared/marked/parse.mjs';
|
||||
import {getHighlighterInstance} from '../shiki/shiki.mjs';
|
||||
import {addApiLinksToHtml} from './code-transforms.mjs';
|
||||
|
||||
const JS_DOC_USAGE_NOTE_TAGS: Set<string> = new Set(['remarks', 'usageNotes', 'example']);
|
||||
export const JS_DOC_SEE_TAG = 'see';
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@
|
|||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {MemberEntry, MemberTags, MemberType} from '../entities.mjs';
|
||||
import {MemberEntry, MemberTags, MemberType, type DocEntry} from '../entities.mjs';
|
||||
import {isHiddenEntry} from '../entities/categorization.mjs';
|
||||
import type {MemberEntryRenderable} from '../entities/renderables.mjs';
|
||||
|
||||
import {HasMembers, HasModuleName, HasRenderableMembers, HasRepo} from '../entities/traits.mjs';
|
||||
import {addRenderableCodeToc} from './code-transforms.mjs';
|
||||
|
||||
import {
|
||||
addHtmlDescription,
|
||||
|
|
@ -39,6 +41,13 @@ export function filterLifecycleMethods(members: MemberEntry[]): MemberEntry[] {
|
|||
return members.filter((m) => !lifecycleMethods.includes(m.name));
|
||||
}
|
||||
|
||||
/** Filters out members that come from merged namespace declarations. */
|
||||
export function filterMergedNamespaceMembers(members: MemberEntry[]): MemberEntry[] {
|
||||
return members.filter(
|
||||
(m) => m.memberType !== MemberType.Interface && m.memberType !== MemberType.TypeAlias,
|
||||
);
|
||||
}
|
||||
|
||||
/** Merges getter and setter entries with the same name into a single entry. */
|
||||
export function mergeGettersAndSetters(members: MemberEntry[]): MemberEntry[] {
|
||||
const getters = new Set<string>();
|
||||
|
|
@ -64,20 +73,39 @@ export function mergeGettersAndSetters(members: MemberEntry[]): MemberEntry[] {
|
|||
);
|
||||
}
|
||||
|
||||
export function addRenderableMembers<T extends HasMembers & HasModuleName & HasRepo>(
|
||||
function addDisplayName<T extends MemberEntryRenderable>(entry: T, parentName: string): T {
|
||||
return entry.memberType === MemberType.Interface || entry.memberType === MemberType.TypeAlias
|
||||
? {...entry, displayName: `${parentName}.${entry.name}`}
|
||||
: entry;
|
||||
}
|
||||
|
||||
export async function addRenderableMembers<T extends HasMembers & HasModuleName & HasRepo>(
|
||||
entry: T,
|
||||
): T & HasRenderableMembers {
|
||||
const members = entry.members
|
||||
.filter((member) => !isHiddenEntry(member))
|
||||
.map((member) =>
|
||||
parentName: string,
|
||||
): Promise<T & HasRenderableMembers> {
|
||||
const members = (
|
||||
await Promise.all(
|
||||
// TODO: remove `?? []` when components repo is updated to include members array on type aliases.
|
||||
(entry.members ?? [])
|
||||
.filter((member) => !isHiddenEntry(member))
|
||||
.map((member) => {
|
||||
if (member.memberType === MemberType.Interface) {
|
||||
return addRenderableCodeToc(
|
||||
addModuleName(member as DocEntry & MemberEntry, entry.moduleName),
|
||||
);
|
||||
} else {
|
||||
return addModuleName(member, entry.moduleName);
|
||||
}
|
||||
}),
|
||||
)
|
||||
).map((member) =>
|
||||
addDisplayName(
|
||||
setEntryFlags(
|
||||
addHtmlDescription(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(addRepo(addModuleName(member, entry.moduleName), entry.repo)),
|
||||
),
|
||||
),
|
||||
addHtmlDescription(addHtmlUsageNotes(addHtmlJsDocTagComments(addRepo(member, entry.repo)))),
|
||||
),
|
||||
);
|
||||
parentName,
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
...entry,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import {TypeAliasEntry} from '../entities.mjs';
|
||||
import {TypeAliasEntryRenderable} from '../entities/renderables.mjs';
|
||||
import type {HasMembers} from '../entities/traits.mjs';
|
||||
import {addRenderableCodeToc} from './code-transforms.mjs';
|
||||
import {
|
||||
addHtmlAdditionalLinks,
|
||||
|
|
@ -27,22 +26,20 @@ export async function getTypeAliasRenderable(
|
|||
moduleName: string,
|
||||
repo: string,
|
||||
): Promise<TypeAliasEntryRenderable> {
|
||||
const entryWithModuleAndRepo = addRepo(addModuleName(typeAliasEntry, moduleName), repo);
|
||||
|
||||
const renderableMembers = hasMembers(entryWithModuleAndRepo)
|
||||
? (await addRenderableMembers(entryWithModuleAndRepo)).members
|
||||
: undefined;
|
||||
|
||||
return setEntryFlags(
|
||||
await addRenderableCodeToc({
|
||||
...addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(addHtmlJsDocTagComments(addHtmlDescription(entryWithModuleAndRepo))),
|
||||
await addRenderableCodeToc(
|
||||
addHtmlAdditionalLinks(
|
||||
addHtmlUsageNotes(
|
||||
addHtmlJsDocTagComments(
|
||||
addHtmlDescription(
|
||||
await addRenderableMembers(
|
||||
addRepo(addModuleName(typeAliasEntry, moduleName), repo),
|
||||
typeAliasEntry.name,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
members: renderableMembers,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function hasMembers(typeAlias: TypeAliasEntry): typeAlias is TypeAliasEntry & HasMembers {
|
||||
return typeAlias.members !== undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,6 +161,11 @@ $code-font-size: 0.875rem;
|
|||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
&.embedded {
|
||||
border-width: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.shiki {
|
||||
|
|
@ -334,7 +339,7 @@ $code-font-size: 0.875rem;
|
|||
text-align: right;
|
||||
padding-block: 0.25rem;
|
||||
}
|
||||
|
||||
|
||||
.line {
|
||||
&.highlighted {
|
||||
background-color: color-mix(in srgb, var(--bright-blue) 9%, var(--page-background));
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ export enum MemberType {
|
|||
Getter = 'getter',
|
||||
Setter = 'setter',
|
||||
EnumItem = 'enum_item',
|
||||
Interface = 'interface',
|
||||
TypeAlias = 'type_alias',
|
||||
}
|
||||
|
||||
export enum DecoratorType {
|
||||
|
|
@ -107,7 +109,7 @@ export interface ConstantEntry extends DocEntry {
|
|||
/** Documentation entity for a type alias. */
|
||||
export interface TypeAliasEntry extends ConstantEntry {
|
||||
generics: GenericEntry[];
|
||||
members?: DocEntry[]; // For merged namespaces
|
||||
members: MemberEntry[]; // For merged namespaces
|
||||
}
|
||||
|
||||
/** Documentation entity for a TypeScript class. */
|
||||
|
|
@ -194,6 +196,12 @@ export interface PropertyEntry extends MemberEntry {
|
|||
/** Sub-entry for a class method. */
|
||||
export type MethodEntry = MemberEntry & FunctionEntry;
|
||||
|
||||
/** Sub-entry for an interface (included via namespace). */
|
||||
export type InterfaceMemberEntry = MemberEntry & InterfaceEntry;
|
||||
|
||||
/** Sub-entry for a type alias (included via namespace). */
|
||||
export type TypeAliasMemberEntry = MemberEntry & TypeAliasEntry;
|
||||
|
||||
/** Sub-entry for a single function parameter. */
|
||||
export interface ParameterEntry {
|
||||
name: string;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ import {
|
|||
DocEntry,
|
||||
DocEntryWithSourceInfo,
|
||||
EntryType,
|
||||
MemberType,
|
||||
type InterfaceEntry,
|
||||
type MemberEntry,
|
||||
type NamespaceEntry,
|
||||
type TypeAliasEntry,
|
||||
} from './entities';
|
||||
|
|
@ -150,16 +153,31 @@ export class DocsExtractor {
|
|||
// For now, we only support merging a type alias and a namespace.
|
||||
const typeAlias = entries.find(isTypeAliasEntry);
|
||||
const namespace = entries.find(isNamespaceEntry);
|
||||
const interfaceEntry = entries.find(isInterfaceEntry);
|
||||
|
||||
if (typeAlias && namespace) {
|
||||
typeAlias.members = namespace.members;
|
||||
typeAlias.members.push(...this.getTypeMembersFromNamespace(namespace));
|
||||
return typeAlias;
|
||||
}
|
||||
if (interfaceEntry && namespace) {
|
||||
interfaceEntry.members.push(...this.getTypeMembersFromNamespace(namespace));
|
||||
}
|
||||
}
|
||||
|
||||
return entry ?? null;
|
||||
}
|
||||
|
||||
private getTypeMembersFromNamespace(namespace: NamespaceEntry): MemberEntry[] {
|
||||
return namespace.members
|
||||
.filter((e) => isInterfaceEntry(e) || isTypeAliasEntry(e))
|
||||
.map((e) => ({
|
||||
...e,
|
||||
memberType:
|
||||
e.entryType === EntryType.Interface ? MemberType.Interface : MemberType.TypeAlias,
|
||||
memberTags: [],
|
||||
}));
|
||||
}
|
||||
|
||||
/** Extract the doc entry for a single declaration. */
|
||||
private extractDeclaration(node: ts.Declaration): DocEntry | null {
|
||||
// Ignore anonymous classes.
|
||||
|
|
@ -277,3 +295,7 @@ function isTypeAliasEntry(e: DocEntry | null): e is TypeAliasEntry {
|
|||
function isNamespaceEntry(e: DocEntry | null): e is NamespaceEntry {
|
||||
return e?.entryType === EntryType.Namespace;
|
||||
}
|
||||
|
||||
function isInterfaceEntry(e: DocEntry | null): e is InterfaceEntry {
|
||||
return e?.entryType === EntryType.Interface;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
import ts from 'typescript';
|
||||
|
||||
import {EntryType} from './entities';
|
||||
import {extractJsDocDescription, extractJsDocTags, extractRawJsDoc} from './jsdoc_extractor';
|
||||
import {extractGenerics} from './generics_extractor';
|
||||
import {extractJsDocDescription, extractJsDocTags, extractRawJsDoc} from './jsdoc_extractor';
|
||||
|
||||
/** Extract the documentation entry for a type alias. */
|
||||
export function extractTypeAlias(declaration: ts.TypeAliasDeclaration) {
|
||||
|
|
@ -25,5 +25,6 @@ export function extractTypeAlias(declaration: ts.TypeAliasDeclaration) {
|
|||
rawComment: extractRawJsDoc(declaration),
|
||||
description: extractJsDocDescription(declaration),
|
||||
jsdocTags: extractJsDocTags(declaration),
|
||||
members: [],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue