Skip to content

Commit 664ae8b

Browse files
authored
Make heading from stepper visible in outline (#3301)
1 parent fa3d2aa commit 664ae8b

File tree

1 file changed

+86
-42
lines changed

1 file changed

+86
-42
lines changed

packages/gitbook/src/lib/document-sections.ts

Lines changed: 86 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { JSONDocument } from '@gitbook/api';
1+
import type { DocumentBlock, JSONDocument } from '@gitbook/api';
22
import type { GitBookAnyContext } from '@v2/lib/context';
33

44
import { getNodeText } from './document';
@@ -19,58 +19,102 @@ export interface DocumentSection {
1919
export async function getDocumentSections(
2020
context: GitBookAnyContext,
2121
document: JSONDocument
22+
): Promise<DocumentSection[]> {
23+
return getSectionsFromNodes(document.nodes, context);
24+
}
25+
26+
/**
27+
* Extract a list of sections from a list of nodes.
28+
*/
29+
async function getSectionsFromNodes(
30+
nodes: DocumentBlock[],
31+
context: GitBookAnyContext
2232
): Promise<DocumentSection[]> {
2333
const sections: DocumentSection[] = [];
2434
let depth = 0;
2535

26-
for (const block of document.nodes) {
27-
if ((block.type === 'heading-1' || block.type === 'heading-2') && block.meta?.id) {
28-
if (block.type === 'heading-1') {
36+
for (const block of nodes) {
37+
switch (block.type) {
38+
case 'heading-1': {
39+
const id = block.meta?.id;
40+
if (!id) {
41+
continue;
42+
}
2943
depth = 1;
30-
}
31-
const title = getNodeText(block);
32-
const id = block.meta.id;
33-
34-
sections.push({
35-
id,
36-
title,
37-
depth: block.type === 'heading-1' ? 1 : depth > 0 ? 2 : 1,
38-
});
39-
}
40-
41-
if ((block.type === 'swagger' || block.type === 'openapi-operation') && block.meta?.id) {
42-
const { data: operation } = await resolveOpenAPIOperationBlock({
43-
block,
44-
context,
45-
});
46-
if (operation) {
44+
const title = getNodeText(block);
4745
sections.push({
48-
id: block.meta.id,
49-
tag: operation.method.toUpperCase(),
50-
title: operation.operation.summary || operation.path,
46+
id,
47+
title,
5148
depth: 1,
52-
deprecated: operation.operation.deprecated,
5349
});
50+
continue;
5451
}
55-
}
56-
57-
if (
58-
block.type === 'openapi-schemas' &&
59-
!block.data.grouped &&
60-
block.meta?.id &&
61-
block.data.schemas.length === 1
62-
) {
63-
const { data } = await resolveOpenAPISchemasBlock({
64-
block,
65-
context,
66-
});
67-
const schema = data?.schemas[0];
68-
if (schema) {
52+
case 'heading-2': {
53+
const id = block.meta?.id;
54+
if (!id) {
55+
continue;
56+
}
57+
const title = getNodeText(block);
6958
sections.push({
70-
id: block.meta.id,
71-
title: `The ${schema.name} object`,
72-
depth: 1,
59+
id,
60+
title,
61+
depth: depth > 0 ? 2 : 1,
62+
});
63+
continue;
64+
}
65+
case 'stepper': {
66+
const stepNodes = await Promise.all(
67+
block.nodes.map(async (step) => getSectionsFromNodes(step.nodes, context))
68+
);
69+
for (const stepSections of stepNodes) {
70+
sections.push(...stepSections);
71+
}
72+
continue;
73+
}
74+
case 'swagger':
75+
case 'openapi-operation': {
76+
const id = block.meta?.id;
77+
if (!id) {
78+
continue;
79+
}
80+
const { data: operation } = await resolveOpenAPIOperationBlock({
81+
block,
82+
context,
83+
});
84+
if (operation) {
85+
sections.push({
86+
id,
87+
tag: operation.method.toUpperCase(),
88+
title: operation.operation.summary || operation.path,
89+
depth: 1,
90+
deprecated: operation.operation.deprecated,
91+
});
92+
}
93+
continue;
94+
}
95+
case 'openapi-schemas': {
96+
const id = block.meta?.id;
97+
if (!id) {
98+
continue;
99+
}
100+
if (block.data.grouped || block.data.schemas.length !== 1) {
101+
// Skip grouped schemas, they are not sections
102+
continue;
103+
}
104+
105+
const { data } = await resolveOpenAPISchemasBlock({
106+
block,
107+
context,
73108
});
109+
const schema = data?.schemas[0];
110+
if (schema) {
111+
sections.push({
112+
id,
113+
title: `The ${schema.name} object`,
114+
depth: 1,
115+
});
116+
}
117+
continue;
74118
}
75119
}
76120
}

0 commit comments

Comments
 (0)