Skip to content

Commit ef583ee

Browse files
committed
fix(core): added support for@group none, @category none and @disableGroups
1 parent 1d044b8 commit ef583ee

21 files changed

+1427
-265
lines changed

.changeset/thick-poets-buy.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'typedoc-plugin-markdown': patch
3+
---
4+
5+
- Added support for TypeDoc's v0.28.2 features `@group none`, `@category none` and `@disableGroups`.

docs/content/docs/options/display-options.mdx

-18
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,6 @@ Options that are used to configure how the output is structured and displayed.
4040
}
4141
```
4242

43-
## hideGroupHeadings
44-
45-
<Callout emoji="💡">
46-
Excludes grouping by kind so all members are rendered at the same level.
47-
</Callout>
48-
49-
> Accepts a boolean value. Defaults to `false`.
50-
51-
By default members are grouped by kind (eg Classes, Functions etc).
52-
53-
This creates a flat structure where all members are displayed at the same heading level.
54-
55-
```json filename="typedoc.json"
56-
{
57-
"hideGroupHeadings": false
58-
}
59-
```
60-
6143
## useCodeBlocks
6244

6345
<Callout emoji="💡">Wraps signatures and declarations in code blocks.</Callout>

docs/content/docs/options/index.mdx

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ Options that are used to configure how the output is structured and displayed.
3232
| [hidePageHeader](./options/display-options.mdx#hidepageheader) | Do not print page header. |
3333
| [hideBreadcrumbs](./options/display-options.mdx#hidebreadcrumbs) | Do not print breadcrumbs. |
3434
| [hidePageTitle](./options/display-options.mdx#hidepagetitle) | Do not print page title. |
35-
| [hideGroupHeadings](./options/display-options.mdx#hidegroupheadings) | Excludes grouping by kind so all members are rendered at the same level. |
3635
| [useCodeBlocks](./options/display-options.mdx#usecodeblocks) | Wraps signatures and declarations in code blocks. |
3736
| [expandObjects](./options/display-options.mdx#expandobjects) | Expand objects inside declarations. |
3837
| [expandParameters](./options/display-options.mdx#expandparameters) | Expand parameters in signature parentheses to display type information. |

packages/typedoc-plugin-markdown/src/options/declarations.ts

+2
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ export const hidePageTitle: Partial<DeclarationOption> = {
240240
* This creates a flat structure where all members are displayed at the same heading level.
241241
*
242242
* @category Display
243+
*
244+
* @hidden
243245
*/
244246
export const hideGroupHeadings: Partial<DeclarationOption> = {
245247
help: 'Excludes grouping by kind so all members are rendered at the same level.',

packages/typedoc-plugin-markdown/src/theme/context/partials/comments.comment.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ export function comment(
3030

3131
//Add flags and summary
3232
if (opts.showSummary) {
33-
// Add flags
3433
const flagsNotRendered: `@${string}`[] = [
3534
'@showCategories',
3635
'@showGroups',
3736
'@hideCategories',
3837
'@hideGroups',
38+
'@disableGroups',
3939
];
4040

4141
const flags: string[] = [];

packages/typedoc-plugin-markdown/src/theme/context/partials/container.body.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { heading, horizontalRule } from '@plugin/libs/markdown/index.js';
22
import { MarkdownThemeContext } from '@plugin/theme/index.js';
3+
import {
4+
isNoneSection,
5+
sortNoneSectionFirst,
6+
} from '@plugin/theme/lib/index.js';
37
import {
48
ContainerReflection,
59
DeclarationReflection,
10+
ReflectionGroup,
611
ReflectionKind,
712
} from 'typedoc';
813

@@ -38,11 +43,13 @@ export function body(
3843
);
3944
} else {
4045
if (model.groups?.length) {
41-
model.groups.forEach((group, i) => {
46+
model.groups.sort(sortNoneSectionFirst).forEach((group, i) => {
4247
if (
4348
group.children.every((child) => this.router.hasOwnDocument(child))
4449
) {
45-
md.push(heading(options.headingLevel, group.title));
50+
if (!isNoneSection(group)) {
51+
md.push(heading(options.headingLevel, group.title));
52+
}
4653
md.push(this.partials.groupIndex(group));
4754
} else {
4855
md.push(
@@ -68,6 +75,20 @@ export function body(
6875
kind: model.kind,
6976
}),
7077
);
78+
} else if (
79+
model.children?.every((child) => this.router.hasOwnDocument(child))
80+
) {
81+
md.push(
82+
this.partials.groupIndex({
83+
children: model.children,
84+
} as ReflectionGroup),
85+
);
86+
} else {
87+
md.push(
88+
this.partials.members(model.children as DeclarationReflection[], {
89+
headingLevel: options.headingLevel,
90+
}),
91+
);
7192
}
7293
}
7394
}

packages/typedoc-plugin-markdown/src/theme/context/partials/container.categories.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { heading } from '@plugin/libs/markdown/index.js';
22
import { MarkdownThemeContext } from '@plugin/theme/index.js';
3+
import {
4+
isNoneSection,
5+
sortNoneSectionFirst,
6+
} from '@plugin/theme/lib/index.js';
37
import {
48
DeclarationReflection,
59
ReflectionCategory,
@@ -12,9 +16,11 @@ export function categories(
1216
options: { headingLevel: number },
1317
) {
1418
const md: string[] = [];
15-
models.forEach((category) => {
19+
models.sort(sortNoneSectionFirst).forEach((category) => {
1620
if (category.children.every((child) => this.router.hasOwnDocument(child))) {
17-
md.push(heading(options.headingLevel, category.title));
21+
if (!isNoneSection(category)) {
22+
md.push(heading(options.headingLevel, category.title));
23+
}
1824
if (category.description) {
1925
md.push(this.helpers.getCommentParts(category.description));
2026
}
@@ -24,13 +30,17 @@ export function categories(
2430
(child) => child.kind !== ReflectionKind.Constructor,
2531
);
2632
if (categoryChildren.length) {
27-
md.push(heading(options.headingLevel, category.title));
33+
if (!isNoneSection(category)) {
34+
md.push(heading(options.headingLevel, category.title));
35+
}
2836
if (category.description) {
2937
md.push(this.helpers.getCommentParts(category.description));
3038
}
3139
md.push(
3240
this.partials.members(categoryChildren as DeclarationReflection[], {
33-
headingLevel: options.headingLevel + 1,
41+
headingLevel: isNoneSection(category)
42+
? options.headingLevel
43+
: options.headingLevel + 1,
3444
}),
3545
);
3646
}

packages/typedoc-plugin-markdown/src/theme/context/partials/container.groups.ts

+24-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { heading } from '@plugin/libs/markdown/index.js';
22
import { MarkdownThemeContext } from '@plugin/theme/index.js';
3+
import {
4+
isNoneSection,
5+
sortNoneSectionFirst,
6+
} from '@plugin/theme/lib/index.js';
37
import {
48
ContainerReflection,
59
DeclarationReflection,
@@ -19,7 +23,7 @@ export function groups(
1923
return groupTitle;
2024
};
2125

22-
model.groups?.forEach((group) => {
26+
model.groups?.sort(sortNoneSectionFirst).forEach((group) => {
2327
if (
2428
group.title === i18n.kind_plural_module() ||
2529
group.children.every((child) => this.router.hasOwnDocument(child))
@@ -31,14 +35,18 @@ export function groups(
3135
if (isPackages) {
3236
md.push(heading(options.headingLevel, i18n.theme_packages()));
3337
} else {
34-
md.push(heading(options.headingLevel, group.title));
38+
if (!isNoneSection(group)) {
39+
md.push(heading(options.headingLevel, group.title));
40+
}
3541
}
3642
if (group.description) {
3743
md.push(this.helpers.getCommentParts(group.description));
3844
}
3945
if (group.categories) {
40-
group.categories.forEach((categoryGroup) => {
41-
md.push(heading(options.headingLevel + 1, categoryGroup.title));
46+
group.categories.sort(sortNoneSectionFirst).forEach((categoryGroup) => {
47+
if (!isNoneSection(categoryGroup)) {
48+
md.push(heading(options.headingLevel + 1, categoryGroup.title));
49+
}
4250
if (categoryGroup.description) {
4351
md.push(this.helpers.getCommentParts(categoryGroup.description));
4452
}
@@ -54,13 +62,17 @@ export function groups(
5462
} else {
5563
const isEventProps = getGroupTitle(group.title) === 'Events';
5664
if (group.categories) {
57-
md.push(heading(options.headingLevel, getGroupTitle(group.title)));
65+
if (!isNoneSection(group)) {
66+
md.push(heading(options.headingLevel, getGroupTitle(group.title)));
67+
}
5868
if (group.description) {
5969
md.push(this.helpers.getCommentParts(group.description));
6070
}
6171
md.push(
6272
this.partials.categories(group.categories, {
63-
headingLevel: options.headingLevel + 1,
73+
headingLevel: isNoneSection(group)
74+
? options.headingLevel
75+
: options.headingLevel + 1,
6476
}),
6577
);
6678
} else {
@@ -72,7 +84,9 @@ export function groups(
7284
(child) => child.kind === ReflectionKind.EnumMember,
7385
);
7486

75-
md.push(heading(options.headingLevel, getGroupTitle(group.title)));
87+
if (!isNoneSection(group)) {
88+
md.push(heading(options.headingLevel, getGroupTitle(group.title)));
89+
}
7690

7791
if (group.description) {
7892
md.push(this.helpers.getCommentParts(group.description));
@@ -100,7 +114,9 @@ export function groups(
100114
if (group.children) {
101115
md.push(
102116
this.partials.members(group.children as DeclarationReflection[], {
103-
headingLevel: options.headingLevel + 1,
117+
headingLevel: isNoneSection(group)
118+
? options.headingLevel
119+
: options.headingLevel + 1,
104120
groupTitle: group.title,
105121
}),
106122
);
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export * from './get-hierarchy-roots.js';
2+
export * from './is-none-section.js';
3+
export * from './sort-none-section-first.js';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { MemberSection } from '@plugin/types/index.js';
2+
3+
export function isNoneSection(section: MemberSection): boolean {
4+
return section.title.toLocaleLowerCase() === 'none';
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { MemberSection } from '@plugin/types/theme.js';
2+
import { isNoneSection } from './is-none-section.js';
3+
4+
export function sortNoneSectionFirst(a: MemberSection, b: MemberSection) {
5+
if (isNoneSection(a)) {
6+
return -1;
7+
}
8+
if (isNoneSection(b)) {
9+
return 1;
10+
}
11+
return 0;
12+
}

packages/typedoc-plugin-markdown/src/theme/navigation/navigation-builder.ts

+19-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { isQuoted } from '@plugin/libs/utils/index.js';
22
import { OutputFileStrategy } from '@plugin/options/maps.js';
33
import { MarkdownTheme } from '@plugin/theme/index.js';
4-
import { getHierarchyRoots } from '@plugin/theme/lib/index.js';
4+
import {
5+
getHierarchyRoots,
6+
isNoneSection,
7+
sortNoneSectionFirst,
8+
} from '@plugin/theme/lib/index.js';
59
import { MarkdownRenderer, NavigationItem } from '@plugin/types/index.js';
610
import {
711
DeclarationReflection,
@@ -266,16 +270,19 @@ export class NavigationBuilder {
266270
!this.navigationOptions.excludeCategories &&
267271
child.categories?.length
268272
? child.categories
273+
.sort(sortNoneSectionFirst)
269274
?.map((category) => {
270275
const catChildren = this.getCategoryGroupChildren(category);
271276
return catChildren.length
272-
? {
273-
title: category.title,
274-
...(this.router.hasUrl(category as any) && {
275-
path: this.router.getFullUrl(category as any),
276-
}),
277-
children: catChildren,
278-
}
277+
? isNoneSection(category)
278+
? [...catChildren]
279+
: {
280+
title: category.title,
281+
...(this.router.hasUrl(category as any) && {
282+
path: this.router.getFullUrl(category as any),
283+
}),
284+
children: catChildren,
285+
}
279286
: null;
280287
})
281288
.filter((cat) => Boolean(cat))
@@ -317,12 +324,16 @@ export class NavigationBuilder {
317324
}
318325

319326
return reflection.groups
327+
?.sort(sortNoneSectionFirst)
320328
?.map((group) => {
321329
const groupChildren = this.getGroupChildren(group);
322330
if (groupChildren?.length) {
323331
if (group.owningReflection.kind === ReflectionKind.Document) {
324332
return groupChildren[0];
325333
}
334+
if (isNoneSection(group)) {
335+
return [...groupChildren];
336+
}
326337
return {
327338
title: group.title,
328339
children: groupChildren,

packages/typedoc-plugin-markdown/src/types/theme.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { Options, ReflectionKind } from 'typedoc';
1+
import {
2+
Options,
3+
ReflectionCategory,
4+
ReflectionGroup,
5+
ReflectionKind,
6+
} from 'typedoc';
27

38
/**
49
* The model used to define the package metadata when in packages mode.
@@ -25,3 +30,5 @@ export interface NavigationItem {
2530
* Defines the template type to use for rendering.
2631
*/
2732
export type RenderTemplate<T> = (data: T) => string;
33+
34+
export type MemberSection = ReflectionGroup | ReflectionCategory;

packages/typedoc-plugin-markdown/test/fixtures/config.mjs

-8
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,6 @@ const config = {
129129
},
130130
{
131131
readme: 'none',
132-
membersWithOwnFile: [
133-
'Class',
134-
'Interface',
135-
'Enum',
136-
'TypeAlias',
137-
'Function',
138-
],
139-
hideGroupHeadings: true,
140132
groupOrder: ['Functions', 'Interfaces', '*'],
141133
useHTMLAnchors: true,
142134
indexFormat: 'htmlTable',

packages/typedoc-plugin-markdown/test/fixtures/src/groups/has-categories.ts

+10
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,13 @@ export interface CategoryCInterface2 {}
4545

4646
export interface UnCategorizedInterace {}
4747
export enum UnCategorizedEnum {}
48+
49+
/**
50+
* @category None
51+
*/
52+
export interface ExplicitNoCategoryInterface {}
53+
54+
/**
55+
* @category None
56+
*/
57+
export enum ExplicitNoCategoryEnum {}

packages/typedoc-plugin-markdown/test/fixtures/src/groups/has-custom-groups.ts

+18
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,21 @@ export const variableB2 = true;
2626
* Default grouping
2727
*/
2828
export const variableC = true;
29+
30+
/**
31+
* @group None
32+
*/
33+
export const variableNoGroup1 = true;
34+
/**
35+
* @group None
36+
*/
37+
export const variableNoGroup2 = true;
38+
39+
/**
40+
* @group None
41+
*/
42+
export interface InterfaceNoGroup1 {}
43+
/**
44+
* @group None
45+
*/
46+
export interface InterfaceNoGroup2 {}

0 commit comments

Comments
 (0)