Skip to content

Commit f4601e9

Browse files
authored
[Docs Site] Refactor single-file collections, handle external links (#19900)
1 parent b278f23 commit f4601e9

File tree

9 files changed

+862
-871
lines changed

9 files changed

+862
-871
lines changed

src/components/AnchorHeading.astro

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { z } from "astro:schema";
33
import { marked } from "marked";
44
import { slug as GithubSlug } from "github-slugger";
55
6-
import { rehype } from "rehype";
6+
import { process } from "~/util/rehype";
77
import rehypeAutoLinkHeadings from "~/plugins/rehype/autolink-headings";
88
99
type Props = z.infer<typeof props>;
@@ -20,14 +20,10 @@ const slugified = GithubSlug(slug ?? title);
2020
2121
const tag = `h${depth}` as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
2222
23-
const file = await rehype()
24-
.data("settings", {
25-
fragment: true,
26-
})
27-
.use(rehypeAutoLinkHeadings)
28-
.process(`<${tag} id=${slugified}>${marked.parseInline(title)}</${tag}>`);
29-
30-
const html = file.toString();
23+
const html = await process(
24+
`<${tag} id=${slugified}>${marked.parseInline(title)}</${tag}>`,
25+
[rehypeAutoLinkHeadings],
26+
);
3127
---
3228

3329
<Fragment set:html={html} />

src/components/ExternalResources.astro

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
---
2-
import { getEntry } from "astro:content";
2+
import { getCollection } from "astro:content";
33
import { z } from "astro:schema";
44
5+
import { process } from "~/util/rehype";
6+
import rehypeExternalLinks from "~/plugins/rehype/external-links";
7+
58
type Props = z.infer<typeof props>;
69
710
const props = z.object({
@@ -13,33 +16,34 @@ const props = z.object({
1316
1417
const { type, tags, products, cloudflareOnly } = props.parse(Astro.props);
1518
16-
const resources = await getEntry(type, "index");
17-
18-
if (!resources) {
19-
throw new Error("Failed to load data");
20-
}
21-
22-
const filtered = resources.data.entries.filter((entry) => {
19+
const resources = await getCollection(type, (e) => {
2320
return (
24-
(cloudflareOnly ? entry.cloudflare : true) &&
25-
(tags ? entry.tags?.some((v: string) => tags.includes(v)) : true) &&
21+
(cloudflareOnly ? e.data.cloudflare : true) &&
22+
(tags ? e.data.tags?.some((v: string) => tags.includes(v)) : true) &&
2623
(products
27-
? entry.products?.some((v: string) => products.includes(v))
24+
? e.data.products?.some((v: string) => products.includes(v))
2825
: true)
2926
);
3027
});
3128
32-
filtered.sort((a, b) => Number(b.updated) - Number(a.updated));
29+
if (!resources) {
30+
throw new Error("Failed to load data");
31+
}
32+
33+
resources.sort((a, b) => Number(b.data.updated) - Number(a.data.updated));
3334
---
3435

3536
<ul>
3637
{
37-
filtered.map((entry) => {
38-
const title = "name" in entry ? entry.name : entry.title;
38+
resources.map(async (e) => {
39+
const anchor = await process(`<a href=${e.data.link}>${e.id}:</a>`, [
40+
rehypeExternalLinks,
41+
]);
42+
3943
return (
4044
<li>
41-
<a href={entry.link}>{title}:</a>
42-
<span>{entry.description}</span>
45+
<Fragment set:html={anchor} />
46+
<span>{e.data.description}</span>
4347
</li>
4448
);
4549
})

src/components/ListTutorials.astro

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
---
2-
import { getCollection, getEntry, type InferEntrySchema } from "astro:content";
2+
import { getCollection, getEntry, type CollectionEntry } from "astro:content";
33
import { formatDistance } from "date-fns";
44
5+
import { process } from "~/util/rehype";
6+
import rehypeExternalLinks from "~/plugins/rehype/external-links";
7+
8+
type DocsEntry = CollectionEntry<"docs">;
9+
type VideoEntry = CollectionEntry<"videos">;
10+
11+
const tutorials: Array<DocsEntry | VideoEntry> = [];
12+
513
const currentSection = Astro.params.slug?.split("/")[0];
614
const currentProduct = await getEntry("products", currentSection!);
715
@@ -13,7 +21,7 @@ if (!currentProduct) {
1321
1422
const productTitle = currentProduct.data.product.title;
1523
16-
const tutorials = await getCollection("docs", (entry) => {
24+
const docs = await getCollection("docs", (entry) => {
1725
return (
1826
// pcx_content_type: tutorial
1927
entry.data.pcx_content_type === "tutorial" &&
@@ -26,47 +34,17 @@ const tutorials = await getCollection("docs", (entry) => {
2634
);
2735
});
2836
29-
type VideoEntry = InferEntrySchema<"videos">["entries"][number];
30-
31-
type FinalTutorials = {
32-
slug?: string;
33-
data:
34-
| ({ type: "docs" } & InferEntrySchema<"docs">)
35-
| ({ type: "videos" } & VideoEntry);
36-
}[];
37-
38-
const finalTutorials: FinalTutorials = tutorials.map((x) => ({
39-
slug: x.id,
40-
data: {
41-
type: "docs",
42-
...x.data,
43-
},
44-
}));
45-
46-
const videos = await getEntry("videos", "index");
47-
48-
if (!videos) {
49-
throw new Error("Failed to load data");
50-
}
37+
tutorials.push(...docs);
5138
52-
const filteredVideos = videos.data.entries.filter((x) =>
53-
x.products.some(
39+
const videos = await getCollection("videos", (entry) => {
40+
return entry.data.products.some(
5441
(v: string) => v.toUpperCase() === productTitle.toUpperCase(),
55-
),
56-
);
57-
58-
if (filteredVideos) {
59-
filteredVideos.forEach((x) =>
60-
finalTutorials.push({
61-
data: {
62-
type: "videos",
63-
...x,
64-
},
65-
}),
6642
);
67-
}
43+
});
44+
45+
tutorials.push(...videos);
6846
69-
finalTutorials.sort((a, b) => Number(b.data.updated) - Number(a.data.updated));
47+
tutorials.sort((a, b) => Number(b.data.updated) - Number(a.data.updated));
7048
7149
const timeAgo = (date?: Date) => {
7250
if (!date) return undefined;
@@ -85,15 +63,23 @@ const timeAgo = (date?: Date) => {
8563
</thead>
8664
<tbody>
8765
{
88-
finalTutorials.map((tutorial) => {
66+
tutorials.map(async (tutorial) => {
67+
const title =
68+
tutorial.collection === "docs" ? tutorial.data.title : tutorial.id;
69+
8970
const href =
90-
tutorial.data.type === "docs"
91-
? `/${tutorial.slug}/`
71+
tutorial.collection === "docs"
72+
? `/${tutorial.id}/`
9273
: tutorial.data.link;
74+
75+
const anchor = await process(`<a href=${href}>${title}</a>`, [
76+
rehypeExternalLinks,
77+
]);
78+
9379
return (
9480
<tr>
9581
<td>
96-
<a href={href}>{tutorial.data.title}</a>
82+
<Fragment set:html={anchor} />
9783
</td>
9884
<td>{timeAgo(tutorial.data.updated)}</td>
9985
<td>{tutorial.data.content_type}</td>

src/content.config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { z, defineCollection } from "astro:content";
33
import { docsLoader, i18nLoader } from "@astrojs/starlight/loaders";
44
import { docsSchema, i18nSchema } from "@astrojs/starlight/schema";
55

6-
import { glob } from "astro/loaders";
6+
import { glob, file } from "astro/loaders";
77

88
import {
99
appsSchema,
@@ -95,11 +95,11 @@ export const collections = {
9595
schema: workersAiModelsSchema,
9696
}),
9797
videos: defineCollection({
98-
loader: dataLoader("videos"),
98+
loader: file("src/content/videos/index.yaml"),
9999
schema: videosSchema,
100100
}),
101101
apps: defineCollection({
102-
loader: dataLoader("apps"),
102+
loader: file("src/content/apps/index.yaml"),
103103
schema: appsSchema,
104104
}),
105105
"warp-releases": defineCollection({

0 commit comments

Comments
 (0)