Skip to content

Commit a432b35

Browse files
committed
support new @propertyTableDoc tag; handle object properties that include only callable members
1 parent 196fba4 commit a432b35

3 files changed

Lines changed: 328 additions & 21 deletions

File tree

.typedoc/custom-theme.mjs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,13 @@ class ClerkMarkdownThemeContext extends MarkdownThemeContext {
921921

922922
// On allowlisted output pages only, drop function-valued interface/class properties from property tables (property syntax with function types). Other pages unchanged.
923923
const allowlisted = pageMatchesAllowlist(this.page?.url, REFERENCE_OBJECTS_LIST);
924-
const filtered = allowlisted ? model.filter(prop => !isCallableInterfaceProperty(prop, this.helpers)) : model;
924+
const filtered = allowlisted
925+
? model.filter(
926+
prop =>
927+
!isCallableInterfaceProperty(prop, this.helpers) &&
928+
!isCallableOnlyNamespaceProperty(prop, this.helpers),
929+
)
930+
: model;
925931
return superPartials.propertiesTable(filtered, options);
926932
},
927933
/**
@@ -1561,6 +1567,51 @@ function isCallableInterfaceProperty(prop, helpers) {
15611567
return isCallablePropertyValueType(t, helpers, new Set());
15621568
}
15631569

1570+
/**
1571+
* Inline object type whose **direct** members are exclusively callables (e.g. `emailCode: { sendCode, verifyCode }` in `SignInFutureResource`).
1572+
* Omitted from reference-object property tables; nested callables are documented via extract-methods.
1573+
*
1574+
* If any direct member is not callable, the parent stays in the property table. Use the @propertyTableDoc tag on non-callable members to avoid this behavior; it will create a page for that non-callable member in /methods that contains a heading and property table. (See `emailLink` in `SignInFutureResource` for an example; `emailLink.verification` is not callable and uses the @propertyTableDoc tag.)
1575+
*
1576+
* @param {import('typedoc').DeclarationReflection} prop
1577+
* @param {import('typedoc-plugin-markdown').MarkdownThemeContext['helpers']} helpers
1578+
*/
1579+
function isCallableOnlyNamespaceProperty(prop, helpers) {
1580+
const t =
1581+
(prop.kind === ReflectionKind.Property || prop.kind === ReflectionKind.Variable) && prop.type
1582+
? prop.type
1583+
: helpers.getDeclarationType(prop);
1584+
let cur = /** @type {import('typedoc').SomeType | undefined} */ (t);
1585+
while (
1586+
cur &&
1587+
typeof cur === 'object' &&
1588+
/** @type {{ type?: string }} */ (cur).type === 'optional' &&
1589+
'elementType' in cur
1590+
) {
1591+
cur = /** @type {import('typedoc').SomeType} */ (/** @type {import('typedoc').OptionalType} */ (cur).elementType);
1592+
}
1593+
if (!(cur instanceof ReflectionType)) {
1594+
return false;
1595+
}
1596+
const children = cur.declaration?.children ?? [];
1597+
if (children.length === 0) {
1598+
return false;
1599+
}
1600+
for (const c of children) {
1601+
if (
1602+
c.kind !== ReflectionKind.Property &&
1603+
c.kind !== ReflectionKind.Variable &&
1604+
c.kind !== ReflectionKind.Accessor
1605+
) {
1606+
return false;
1607+
}
1608+
if (!isCallableInterfaceProperty(c, helpers)) {
1609+
return false;
1610+
}
1611+
}
1612+
return true;
1613+
}
1614+
15641615
/**
15651616
* True when the property's value type is callable (function type, union/intersection of callables, or reference to a type alias of a function type). Object types with properties (e.g. namespaces) stay false.
15661617
* E.g. `navigate: CustomNavigation` in clerk.ts
@@ -1644,4 +1695,4 @@ function isCallablePropertyValueType(t, helpers, seenReflectionIds) {
16441695
return false;
16451696
}
16461697

1647-
export { isCallableInterfaceProperty };
1698+
export { isCallableInterfaceProperty, isCallableOnlyNamespaceProperty };

0 commit comments

Comments
 (0)