Skip to content

Commit 1cd63f1

Browse files
authored
[Docs Site] Add index.md for CF1 docs (#20813)
* [Docs Site] Add index.md for CF1 docs * remove test * lift lang from pre attribute to code classname * unwrap tabs * allow img, add base url to a and href, fix mermaid
1 parent c90eda8 commit 1cd63f1

File tree

5 files changed

+241
-11
lines changed

5 files changed

+241
-11
lines changed

package-lock.json

Lines changed: 93 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"fast-xml-parser": "5.0.8",
7171
"github-slugger": "2.0.0",
7272
"globals": "16.0.0",
73+
"hast-util-select": "6.0.4",
7374
"hastscript": "9.0.1",
7475
"he": "1.2.0",
7576
"jsonc-parser": "3.3.1",
@@ -97,9 +98,12 @@
9798
"rehype-autolink-headings": "7.1.0",
9899
"rehype-external-links": "3.0.0",
99100
"rehype-parse": "9.0.1",
101+
"rehype-remark": "10.0.0",
100102
"rehype-stringify": "10.0.1",
101103
"rehype-title-figure": "0.1.2",
102104
"remark": "15.0.1",
105+
"remark-gfm": "4.0.1",
106+
"remark-stringify": "11.0.0",
103107
"sharp": "0.33.5",
104108
"solarflare-theme": "0.0.4",
105109
"starlight-image-zoom": "0.11.1",
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { APIRoute } from "astro";
2+
import type { InferGetStaticPropsType, GetStaticPaths } from "astro";
3+
4+
import { getCollection } from "astro:content";
5+
import { entryToString } from "~/util/container";
6+
7+
import { process } from "~/util/rehype";
8+
import rehypeParse from "rehype-parse";
9+
import rehypeBaseUrl from "~/plugins/rehype/base-url";
10+
import rehypeFilterElements from "~/plugins/rehype/filter-elements";
11+
import remarkGfm from "remark-gfm";
12+
import rehypeRemark from "rehype-remark";
13+
import remarkStringify from "remark-stringify";
14+
15+
export const getStaticPaths = (async () => {
16+
const entries = await getCollection("docs", (e) => {
17+
return e.id.startsWith("cloudflare-one") && Boolean(e.body);
18+
});
19+
20+
return entries.map((entry) => {
21+
return {
22+
params: {
23+
entry: entry.id.replace("cloudflare-one/", ""),
24+
},
25+
props: {
26+
entry,
27+
},
28+
};
29+
});
30+
}) satisfies GetStaticPaths;
31+
32+
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
33+
34+
export const GET: APIRoute<Props> = async (context) => {
35+
const html = await entryToString(context.props.entry, context.locals);
36+
37+
const md = await process(html, [
38+
rehypeParse,
39+
rehypeBaseUrl,
40+
rehypeFilterElements,
41+
remarkGfm,
42+
rehypeRemark,
43+
remarkStringify,
44+
]);
45+
46+
return new Response(md, {
47+
headers: {
48+
"content-type": "text/markdown",
49+
},
50+
});
51+
};

src/plugins/rehype/base-url.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
import { visit } from "unist-util-visit";
22
import type { Root } from "hast";
33

4+
const REWRITE_ELEMENTS = ["a", "img"];
5+
46
export default function () {
57
return function (tree: Root) {
68
visit(tree, "element", function (element) {
7-
if (element.tagName === "a") {
8-
const href = element.properties.href as string | undefined;
9+
if (REWRITE_ELEMENTS.includes(element.tagName)) {
10+
const property = element.tagName === "a" ? "href" : "src";
11+
const href = element.properties[property] as string | undefined;
912

1013
if (href) {
1114
if (href.startsWith("/")) {
1215
const url = new URL(href, "https://developers.cloudflare.com/");
1316

14-
element.properties.href = url.href;
17+
element.properties[property] = url.href;
1518
}
1619
}
1720
}

src/plugins/rehype/filter-elements.ts

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { SKIP, visit, type VisitorResult } from "unist-util-visit";
22
import type { Root, Element, Parents } from "hast";
3+
import { selectAll } from "hast-util-select";
34

45
const remove = (index: number, parent: Parents): VisitorResult => {
56
parent.children.splice(index, 1);
@@ -38,7 +39,7 @@ const ALLOWED_ELEMENTS = [
3839
"div",
3940
"dl",
4041
"dt",
41-
"figcaption",
42+
// "figcaption",
4243
"figure",
4344
"hr",
4445
"li",
@@ -90,12 +91,19 @@ const ALLOWED_ELEMENTS = [
9091
"th",
9192
"thead",
9293
"tr",
94+
// Images
95+
"img",
9396
// Custom elements
9497
"rule-id",
98+
"starlight-tabs",
99+
"starlight-image-zoom-zoomable",
95100
];
96101

97102
const ALLOWED_ATTRIBUTES: Record<string, string[]> = {
98103
a: ["href", "id", "target"],
104+
pre: ["dataLanguage"],
105+
code: ["className"],
106+
img: ["src", "alt"],
99107
"rule-id": ["id"],
100108
};
101109

@@ -128,6 +136,43 @@ export default function () {
128136
}
129137
}
130138

139+
if (tag === "pre") {
140+
if (classNames.includes("mermaid")) {
141+
const definition = element.children.find(
142+
(child) => child.type === "text",
143+
);
144+
if (!definition) return;
145+
146+
element.children = [
147+
{
148+
type: "element",
149+
tagName: "code",
150+
properties: {
151+
className: ["language-mermaid"],
152+
},
153+
children: [
154+
{
155+
type: "text",
156+
value: definition.value,
157+
},
158+
],
159+
},
160+
];
161+
162+
return;
163+
}
164+
165+
const language = element.properties.dataLanguage;
166+
if (!language) return;
167+
168+
const code = element.children.find(
169+
(child) => child.type === "element" && child.tagName === "code",
170+
);
171+
if (!code) return;
172+
173+
(code as Element).properties.className = [`language-${language}`];
174+
}
175+
131176
if (tag === "rule-id") {
132177
return unwrap(index, parent, {
133178
...element,
@@ -136,6 +181,47 @@ export default function () {
136181
],
137182
});
138183
}
184+
185+
if (tag === "starlight-tabs") {
186+
const tabs = selectAll('[role="tab"]', element);
187+
const panels = selectAll('[role="tabpanel"]', element);
188+
189+
element.tagName = "ul";
190+
element.properties = {};
191+
element.children = [];
192+
193+
for (const tab of tabs) {
194+
const id = (tab.properties?.id as string)?.split("tab-")[1];
195+
if (!id) continue;
196+
197+
const panel = panels.find(
198+
(panel) => panel.properties?.id === `tab-panel-${id}`,
199+
);
200+
if (!panel) continue;
201+
202+
const label = tab.children
203+
.filter((child) => child.type === "text" && child.value.trim())
204+
.map((child) => child.type === "text" && child.value.trim())
205+
.join("");
206+
207+
const el = {
208+
type: "element",
209+
tagName: "li",
210+
properties: {},
211+
children: [
212+
{
213+
type: "element",
214+
tagName: "p",
215+
children: [{ type: "text", value: label }],
216+
properties: {},
217+
},
218+
panel,
219+
],
220+
} as Element;
221+
222+
element.children.push(el);
223+
}
224+
}
139225
}
140226
});
141227
};

0 commit comments

Comments
 (0)