docs(docs-infra): Show API decorators docs

fixes #66129

(cherry picked from commit a056413520)
This commit is contained in:
Matthieu Riegler
2026-01-12 14:23:50 +01:00
committed by Jessica Janiuk
parent 8655913dcc
commit 08d0ac73b1
6 changed files with 95 additions and 13 deletions
@@ -126,11 +126,11 @@ export interface EnumEntry extends DocEntry {
/** Documentation entity for an Angular decorator. */
export interface DecoratorEntry extends DocEntry {
decoratorType: DecoratorType;
members: PropertyEntry[] | null;
signatures?: {
parameters: ParameterEntry[];
jsdocTags: JsDocTagEntry[];
}[];
members: MemberEntry[];
}
/** Documentation entity for an Angular directives and components. */
@@ -75,7 +75,11 @@ export type PipeEntryRenderable = PipeEntry &
members: MemberEntryRenderable[];
};
export type DecoratorEntryRenderable = DecoratorEntry & DocEntryRenderable & HasRenderableToc;
export type DecoratorEntryRenderable = Omit<DecoratorEntry, 'members'> &
DocEntryRenderable &
HasRenderableToc & {
members: PropertyEntryRenderable[];
};
/** Documentation entity for a TypeScript enum augmented transformed content for rendering. */
export type EnumEntryRenderable = EnumEntry &
@@ -116,6 +120,10 @@ export interface MemberEntryRenderable extends MemberEntry {
experimental: {version: string | undefined} | undefined;
}
export interface PropertyEntryRenderable extends MemberEntryRenderable {
type: string;
}
/** Sub-entry for a class method augmented transformed content for rendering. */
export type MethodEntryRenderable = MemberEntryRenderable &
FunctionEntryRenderable & {
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.dev/license
*/
import {JsDocTagEntry, MemberEntry, ParameterEntry} from '../entities.mjs';
import {JsDocTagEntry, MemberEntry, ParameterEntry, PropertyEntry} from '../entities.mjs';
import {
CodeLineRenderable,
@@ -14,6 +14,7 @@ import {
LinkEntryRenderable,
MemberEntryRenderable,
ParameterEntryRenderable,
PropertyEntryRenderable,
} from './renderables.mjs';
/** A doc entry that has jsdoc tags. */
@@ -56,6 +57,10 @@ export interface HasMembers {
members: MemberEntry[];
}
export interface HasPropertyMembers {
members: PropertyEntry[];
}
/** A doc entry that has members groups transformed for rendering. */
export interface HasRenderableMembersGroups {
membersGroups: Map<string, MemberEntryRenderable[]>;
@@ -66,6 +71,10 @@ export interface HasRenderableMembers {
members: MemberEntryRenderable[];
}
export interface HasRenderablePropertyMembers {
members: PropertyEntryRenderable[];
}
/** A doc entry that has an associated JS module name. */
export interface HasModuleName {
moduleName: string;
@@ -7,12 +7,45 @@
*/
import {h} from 'preact';
import {DecoratorEntryRenderable, PropertyEntryRenderable} from '../entities/renderables.mjs';
import {
API_REFERENCE_CONTAINER,
REFERENCE_MEMBER_CARD,
REFERENCE_MEMBER_CARD_BODY,
REFERENCE_MEMBER_CARD_HEADER,
REFERENCE_MEMBER_CARD_ITEM,
REFERENCE_MEMBERS,
} from '../styling/css-classes.mjs';
import {CodeSymbol} from './code-symbols';
import {HeaderApi} from './header-api';
import {RawHtml} from './raw-html';
import {SectionApi} from './section-api';
import {SectionDescription} from './section-description';
import {SectionUsageNotes} from './section-usage-notes';
import {SectionApi} from './section-api';
import {API_REFERENCE_CONTAINER} from '../styling/css-classes.mjs';
import {DecoratorEntryRenderable} from '../entities/renderables.mjs';
export const signatureCard = (
name: string,
member: PropertyEntryRenderable,
opts: {id: string},
) => {
return (
<div id={opts.id} class={REFERENCE_MEMBER_CARD}>
<header class={REFERENCE_MEMBER_CARD_HEADER}>
<h3>{name}</h3>
<div>
<CodeSymbol code={member.type} />
</div>
</header>
<div class={REFERENCE_MEMBER_CARD_BODY}>
<div className={`${REFERENCE_MEMBER_CARD_ITEM}`}>
<p>
<RawHtml value={member.htmlDescription} />
</p>
</div>
</div>
</div>
);
};
/** Component to render a decorator API reference document. */
export function DecoratorReference(entry: DecoratorEntryRenderable) {
@@ -20,6 +53,13 @@ export function DecoratorReference(entry: DecoratorEntryRenderable) {
<div className={API_REFERENCE_CONTAINER}>
<HeaderApi entry={entry} />
<SectionApi entry={entry} />
<div className={REFERENCE_MEMBERS}>
{entry.members.map((member, index) =>
signatureCard(member.name, member, {
id: `${member.name}_${index}`,
}),
)}
</div>
<SectionDescription entry={entry} />
<SectionUsageNotes entry={entry} />
</div>
@@ -16,6 +16,7 @@ import {
addHtmlUsageNotes,
setEntryFlags,
} from './jsdoc-transforms.mjs';
import {addRenderablePropertyMembers} from './member-transforms.mjs';
import {addModuleName} from './module-name.mjs';
import {addRepo} from './repo.mjs';
@@ -25,14 +26,24 @@ export async function getDecoratorRenderable(
moduleName: string,
repo: string,
): Promise<DecoratorEntryRenderable> {
const decoratorEntryWithMembers = {
...decoratorEntry,
members: decoratorEntry.members ?? [],
};
return setEntryFlags(
await addRenderableCodeToc(
addHtmlAdditionalLinks(
addHtmlUsageNotes(
addHtmlJsDocTagComments(
addHtmlDescription(addRepo(addModuleName(decoratorEntry, moduleName), repo)),
await addRenderablePropertyMembers(
addHtmlAdditionalLinks(
addHtmlUsageNotes(
addHtmlJsDocTagComments(
addHtmlDescription(
addRepo(addModuleName(decoratorEntryWithMembers, moduleName), repo),
),
),
),
),
decoratorEntry.name,
),
),
) as DecoratorEntryRenderable;
@@ -10,7 +10,14 @@ import {MemberEntry, MemberTags, MemberType, type DocEntry} from '../entities.mj
import {isHiddenEntry} from '../entities/categorization.mjs';
import type {MemberEntryRenderable} from '../entities/renderables.mjs';
import {HasMembers, HasModuleName, HasRenderableMembers, HasRepo} from '../entities/traits.mjs';
import {
HasMembers,
HasModuleName,
HasPropertyMembers,
HasRenderableMembers,
HasRenderablePropertyMembers,
HasRepo,
} from '../entities/traits.mjs';
import {addRenderableCodeToc} from './code-transforms.mjs';
import {
@@ -85,8 +92,7 @@ export async function addRenderableMembers<T extends HasMembers & HasModuleName
): Promise<T & HasRenderableMembers> {
const members = (
await Promise.all(
// TODO: remove `?? []` when components repo is updated to include members array on type aliases.
(entry.members ?? [])
entry.members
.filter((member) => !isHiddenEntry(member))
.map((member) => {
if (member.memberType === MemberType.Interface) {
@@ -112,3 +118,11 @@ export async function addRenderableMembers<T extends HasMembers & HasModuleName
members,
};
}
export async function addRenderablePropertyMembers<
T extends HasPropertyMembers & HasModuleName & HasRepo,
>(entry: T, parentName: string): Promise<T & HasRenderablePropertyMembers> {
return {
...((await addRenderableMembers(entry, parentName)) as T & HasRenderablePropertyMembers),
};
}