Skip to content

Commit 0eda262

Browse files
committed
Fixes after review
1 parent efbe99d commit 0eda262

File tree

3 files changed

+64
-47
lines changed

3 files changed

+64
-47
lines changed

packages/gitbook/src/lib/pages.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {
88

99
export type AncestorRevisionPage = RevisionPageDocument | RevisionPageGroup;
1010

11-
type ResolvedPageDocument = {
12-
page: RevisionPageDocument;
11+
type ResolvedPagePath<Page extends RevisionPageDocument | RevisionPageGroup> = {
12+
page: Page;
1313
ancestors: AncestorRevisionPage[];
1414
};
1515

@@ -19,7 +19,7 @@ type ResolvedPageDocument = {
1919
export function resolvePagePath(
2020
rootPages: Revision['pages'],
2121
pagePath: string
22-
): ResolvedPageDocument | undefined {
22+
): ResolvedPagePath<RevisionPageDocument> | undefined {
2323
const result = findPageByPath(rootPages, pagePath);
2424

2525
if (!result) {
@@ -29,19 +29,14 @@ export function resolvePagePath(
2929
return resolvePageDocument(result.page, result.ancestors);
3030
}
3131

32-
type ResolvedPageDocumentOrGroup = {
33-
page: RevisionPageDocument | RevisionPageGroup;
34-
ancestors: AncestorRevisionPage[];
35-
};
36-
3732
/**
3833
* Resolve a page path to a page document or group.
3934
* Similar to resolvePagePath but returns both documents and groups.
4035
*/
4136
export function resolvePagePathDocumentOrGroup(
4237
rootPages: Revision['pages'],
4338
pagePath: string
44-
): ResolvedPageDocumentOrGroup | undefined {
39+
): ResolvedPagePath<RevisionPageDocument | RevisionPageGroup> | undefined {
4540
const result = findPageByPath(rootPages, pagePath);
4641

4742
if (!result) {
@@ -57,7 +52,7 @@ export function resolvePagePathDocumentOrGroup(
5752
function findPageByPath(
5853
rootPages: Revision['pages'],
5954
pagePath: string
60-
): ResolvedPageDocumentOrGroup | undefined {
55+
): ResolvedPagePath<RevisionPageDocument | RevisionPageGroup> | undefined {
6156
if (!pagePath) {
6257
const firstPage = resolveFirstDocument(rootPages, []);
6358
if (!firstPage) {
@@ -69,7 +64,7 @@ function findPageByPath(
6964
const iteratePages = (
7065
pages: RevisionPage[],
7166
ancestors: AncestorRevisionPage[]
72-
): ResolvedPageDocumentOrGroup | undefined => {
67+
): ResolvedPagePath<RevisionPageDocument | RevisionPageGroup> | undefined => {
7368
for (const page of pages) {
7469
if (page.type === RevisionPageType.Link || page.type === RevisionPageType.Computed) {
7570
continue;

packages/gitbook/src/routes/llms.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,28 @@ async function getNodesFromSiteSpaces(
141141
})
142142
);
143143
const pages = getIndexablePages(revision.pages);
144-
return getMarkdownForPagesTree(pages, {
145-
siteSpaceUrl,
146-
linker,
147-
heading: options.heading ? siteSpace.title : undefined,
148-
withMarkdownPages: options.withMarkdownPages,
149-
});
144+
145+
const nodes: RootContent[] = [];
146+
147+
// Add the space title as a heading
148+
if (options.heading) {
149+
nodes.push({
150+
type: 'heading',
151+
depth: 2,
152+
children: [{ type: 'text', value: siteSpace.title }],
153+
});
154+
}
155+
156+
// Add the pages as a list
157+
nodes.push(
158+
...(await getMarkdownForPagesTree(pages, {
159+
siteSpaceUrl,
160+
linker,
161+
withMarkdownPages: options.withMarkdownPages,
162+
}))
163+
);
164+
165+
return nodes;
150166
})
151167
);
152168
return all.flat();
@@ -160,7 +176,6 @@ export async function getMarkdownForPagesTree(
160176
options: {
161177
siteSpaceUrl: string;
162178
linker: GitBookLinker;
163-
heading?: string;
164179
withMarkdownPages?: boolean;
165180
}
166181
): Promise<RootContent[]> {
@@ -192,13 +207,6 @@ export async function getMarkdownForPagesTree(
192207
})
193208
);
194209
const nodes: RootContent[] = [];
195-
if (options.heading) {
196-
nodes.push({
197-
type: 'heading',
198-
depth: 2,
199-
children: [{ type: 'text', value: options.heading }],
200-
});
201-
}
202210
nodes.push({
203211
type: 'list',
204212
spread: false,

packages/gitbook/src/routes/markdownPage.ts

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import type { GitBookSiteContext } from '@/lib/context';
22
import { throwIfDataError } from '@/lib/data';
3-
import { isNodeEmpty } from '@/lib/document';
43
import { resolvePagePathDocumentOrGroup } from '@/lib/pages';
54
import { getIndexablePages } from '@/lib/sitemap';
65
import { getMarkdownForPagesTree } from '@/routes/llms';
76
import { type RevisionPageDocument, type RevisionPageGroup, RevisionPageType } from '@gitbook/api';
87
import type { Root } from 'mdast';
8+
import { fromMarkdown } from 'mdast-util-from-markdown';
9+
import { frontmatterFromMarkdown } from 'mdast-util-frontmatter';
10+
import { gfmFromMarkdown } from 'mdast-util-gfm';
911
import { toMarkdown } from 'mdast-util-to-markdown';
12+
import { frontmatter } from 'micromark-extension-frontmatter';
13+
import { gfm } from 'micromark-extension-gfm';
14+
import { remove } from 'unist-util-remove';
1015

1116
/**
1217
* Generate a markdown version of a page.
@@ -26,13 +31,11 @@ export async function servePageMarkdown(context: GitBookSiteContext, pagePath: s
2631
return new Response(`Page "${pagePath}" is not a document or group`, { status: 404 });
2732
}
2833

29-
// Handle group pages and empty document pages with children
30-
const isGroupPage = await shouldTreatAsGroupPage(context, page);
31-
if (isGroupPage) {
34+
// Handle group pages
35+
if (page.type === RevisionPageType.Group) {
3236
return servePageGroup(context, page);
3337
}
3438

35-
// Handle regular document pages
3639
const markdown = await throwIfDataError(
3740
context.dataFetcher.getRevisionPageMarkdown({
3841
spaceId: context.space.id,
@@ -41,6 +44,11 @@ export async function servePageMarkdown(context: GitBookSiteContext, pagePath: s
4144
})
4245
);
4346

47+
// Handle empty document pages which have children
48+
if (isEmptyPage(markdown) && page.pages.length > 0) {
49+
return servePageGroup(context, page);
50+
}
51+
4452
return new Response(markdown, {
4553
headers: {
4654
'Content-Type': 'text/markdown; charset=utf-8',
@@ -49,28 +57,33 @@ export async function servePageMarkdown(context: GitBookSiteContext, pagePath: s
4957
}
5058

5159
/**
52-
* Determine if a page should be treated as a group page.
53-
* A page is treated as a group if:
54-
* 1. It's explicitly a group page type, OR
55-
* 2. It's a document page but has empty content (acts as a container)
60+
* Determine if a page is empty.
61+
* A page is empty if it has no content or only a title.
5662
*/
57-
async function shouldTreatAsGroupPage(
58-
context: GitBookSiteContext,
59-
page: RevisionPageDocument | RevisionPageGroup
60-
): Promise<boolean> {
61-
if (page.type === RevisionPageType.Group) {
63+
function isEmptyPage(pageMarkdown: string): boolean {
64+
const trimmedMarkdown = pageMarkdown.trim();
65+
66+
// Check if the markdown is empty
67+
if (!trimmedMarkdown) {
6268
return true;
6369
}
6470

65-
const document = await throwIfDataError(
66-
context.dataFetcher.getRevisionPageDocument({
67-
spaceId: context.space.id,
68-
revisionId: context.revision.id,
69-
pageId: page.id,
70-
})
71-
);
71+
// Parse the markdown to check if it only contains a title
72+
73+
const tree = fromMarkdown(pageMarkdown, {
74+
extensions: [frontmatter(['yaml']), gfm()],
75+
mdastExtensions: [frontmatterFromMarkdown(['yaml']), gfmFromMarkdown()],
76+
});
77+
78+
// Remove frontmatter
79+
remove(tree, 'yaml');
80+
81+
// If the page has no content or only a title, it is empty
82+
if (tree.children.length <= 1 && tree.children[0]?.type === 'heading') {
83+
return true;
84+
}
7285

73-
return isNodeEmpty(document);
86+
return false;
7487
}
7588

7689
/**
@@ -88,6 +101,7 @@ async function servePageGroup(
88101

89102
const indexablePages = getIndexablePages(page.pages);
90103

104+
// Create a markdown tree with the page title as heading and a list of child pages
91105
const markdownTree: Root = {
92106
type: 'root',
93107
children: [

0 commit comments

Comments
 (0)