Skip to content

Commit ccb8035

Browse files
authored
[Docs Site] Add maxDepth to DirectoryListing (#21411)
1 parent 4b97881 commit ccb8035

File tree

3 files changed

+113
-25
lines changed

3 files changed

+113
-25
lines changed

Diff for: src/components/DirectoryListing.astro

+37-23
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,60 @@
22
import { z } from "astro:schema";
33
import { getCollection } from "astro:content";
44
import { sortBySidebarOrder } from "~/util/sidebar";
5-
import { marked } from "marked";
5+
import DirectoryListingItem from "./DirectoryListingItem.astro";
6+
7+
interface PageNode {
8+
page: (typeof allPages)[0];
9+
children: PageNode[];
10+
}
611
712
type Props = z.infer<typeof props>;
813
914
const props = z.object({
1015
descriptions: z.boolean().default(false),
1116
folder: z.string().optional(),
17+
maxDepth: z.number().default(1),
1218
});
1319
14-
let { descriptions, folder } = props.parse(Astro.props);
20+
let { descriptions, folder, maxDepth } = props.parse(Astro.props);
1521
1622
if (!folder) folder = Astro.params.slug!;
1723
18-
const depth = folder.split("/").length + 1;
24+
const baseDepth = folder.split("/").length;
1925
20-
let pages = await getCollection("docs", (page) => {
21-
return (
22-
page.id.startsWith(`${folder}/`) && page.id.split("/").length === depth
23-
);
26+
let allPages = await getCollection("docs", (page) => {
27+
const pageDepth = page.id.split("/").length;
28+
return page.id.startsWith(`${folder}/`) && pageDepth <= baseDepth + maxDepth;
2429
});
2530
26-
pages.sort(sortBySidebarOrder);
31+
allPages.sort(sortBySidebarOrder);
32+
33+
function getChildren(parentPath: string, depth: number) {
34+
return allPages.filter((page) => {
35+
const pagePath = page.id;
36+
const pageDepth = pagePath.split("/").length;
37+
return pageDepth === depth && pagePath.startsWith(parentPath);
38+
});
39+
}
40+
41+
function buildPageTree(parentPath: string, currentDepth: number): PageNode[] {
42+
const children = getChildren(parentPath, currentDepth);
43+
return children.map((page) => ({
44+
page,
45+
children:
46+
currentDepth < baseDepth + maxDepth
47+
? buildPageTree(page.id, currentDepth + 1)
48+
: [],
49+
}));
50+
}
51+
52+
const pageTree = buildPageTree(folder, baseDepth + 1);
2753
---
2854

2955
<ul>
3056
{
31-
pages.map((page) => {
32-
const description = descriptions && page.data.description;
33-
const href = page.data.external_link ?? "/" + page.id + "/";
34-
return (
35-
<li>
36-
<a href={href}>{page.data.title}</a>
37-
{description && (
38-
<>
39-
<span>: </span>
40-
<Fragment set:html={marked.parseInline(description)} />
41-
</>
42-
)}
43-
</li>
44-
);
45-
})
57+
pageTree.map((node) => (
58+
<DirectoryListingItem node={node} descriptions={descriptions} />
59+
))
4660
}
4761
</ul>

Diff for: src/components/DirectoryListingItem.astro

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
import { marked } from "marked";
3+
import type { CollectionEntry } from "astro:content";
4+
5+
interface Props {
6+
node: {
7+
page: CollectionEntry<"docs">;
8+
children: Array<Props["node"]>;
9+
};
10+
descriptions: boolean;
11+
}
12+
13+
const { node, descriptions } = Astro.props;
14+
---
15+
16+
<li>
17+
<a href={node.page.data.external_link ?? "/" + node.page.id + "/"}>
18+
{node.page.data.title}
19+
</a>
20+
{
21+
descriptions && node.page.data.description && (
22+
<>
23+
<span>: </span>
24+
<Fragment set:html={marked.parseInline(node.page.data.description)} />
25+
</>
26+
)
27+
}
28+
{
29+
node.children.length > 0 && (
30+
<ul>
31+
{node.children.map((child) => (
32+
<Astro.self node={child} descriptions={descriptions} />
33+
))}
34+
</ul>
35+
)
36+
}
37+
</li>

Diff for: src/content/docs/style-guide/components/directory-listing.mdx

+39-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,51 @@ import { Render } from "~/components";
88

99
<Render file="directory-listing-definition" />
1010

11-
We also have an optional `descriptions` parameter which - if present - adds in the text from the [front matter `description`](/style-guide/frontmatter/) field.
11+
## Usage
1212

1313
```mdx live
1414
import { DirectoryListing } from "~/components";
1515

16+
<p>
17+
<strong>Default</strong>
18+
</p>
19+
<DirectoryListing folder="workers/wrangler" />
20+
21+
<br />
22+
23+
<p>
24+
<strong>maxDepth</strong>
25+
</p>
26+
<DirectoryListing folder="workers/wrangler" maxDepth={2} />
27+
28+
<p>
29+
<strong>Descriptions</strong>
30+
</p>
1631
<DirectoryListing folder="workers/wrangler" descriptions />
1732
```
1833

34+
## Props
35+
36+
### `folder`
37+
38+
**type:** `string`
39+
40+
The folder path to list contents from. If not provided, defaults to the current page's path.
41+
42+
### `descriptions`
43+
44+
**type:** `boolean`
45+
**default:** `false`
46+
47+
When enabled, shows the [frontmatter `description`](/style-guide/frontmatter/) field for each page in the listing.
48+
49+
### `maxDepth`
50+
51+
**type:** `number`
52+
**default:** `1`
53+
54+
Controls how many levels of nested pages to display. A value of `1` shows only direct children, while higher values will show deeper nesting levels.
55+
1956
## Associated content types
2057

21-
- [Navigation](/style-guide/documentation-content-strategy/content-types/navigation/)
58+
- [Navigation](/style-guide/documentation-content-strategy/content-types/navigation/)

0 commit comments

Comments
 (0)