Skip to content

Commit feebd3e

Browse files
committed
move to Page.astro override, enable pagination
1 parent a60ef38 commit feebd3e

File tree

10 files changed

+178
-158
lines changed

10 files changed

+178
-158
lines changed

astro.config.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import rehypeMermaid from "./src/plugins/rehype/mermaid.ts";
1515
import rehypeAutolinkHeadings from "./src/plugins/rehype/autolink-headings.ts";
1616
import rehypeExternalLinks from "./src/plugins/rehype/external-links.ts";
1717
import rehypeHeadingSlugs from "./src/plugins/rehype/heading-slugs.ts";
18+
import { fileURLToPath } from "url";
1819

1920
async function autogenSections() {
2021
const sections = (
@@ -88,13 +89,10 @@ export default defineConfig({
8889
Footer: "./src/components/overrides/Footer.astro",
8990
Head: "./src/components/overrides/Head.astro",
9091
Hero: "./src/components/overrides/Hero.astro",
91-
LastUpdated: "./src/components/overrides/LastUpdated.astro",
9292
MarkdownContent: "./src/components/overrides/MarkdownContent.astro",
9393
Sidebar: "./src/components/overrides/Sidebar.astro",
94-
PageSidebar: "./src/components/overrides/PageSidebar.astro",
9594
PageTitle: "./src/components/overrides/PageTitle.astro",
9695
SocialIcons: "./src/components/overrides/SocialIcons.astro",
97-
SkipLink: "./src/components/overrides/SkipLink.astro",
9896
TableOfContents: "./src/components/overrides/TableOfContents.astro",
9997
},
10098
sidebar,
@@ -162,4 +160,16 @@ export default defineConfig({
162160
}),
163161
react(),
164162
],
163+
vite: {
164+
resolve: {
165+
alias: {
166+
"./Page.astro": fileURLToPath(
167+
new URL("./src/components/overrides/Page.astro", import.meta.url),
168+
),
169+
"../components/Page.astro": fileURLToPath(
170+
new URL("./src/components/overrides/Page.astro", import.meta.url),
171+
),
172+
},
173+
},
174+
},
165175
});

src/components/overrides/Head.astro

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { differenceInCalendarDays } from "date-fns";
55
import "tippy.js/dist/tippy.css";
66
77
import { getEntry } from "astro:content";
8-
import { getPageDescription } from "~/util/description";
98
109
const currentSection = Astro.url.pathname.split("/")[1];
1110
@@ -139,13 +138,7 @@ if (currentSection) {
139138
}
140139
}
141140
142-
Astro.props.entry.data.description = await getPageDescription(
143-
Astro.props.entry,
144-
Astro.locals,
145-
);
146-
147141
// Adding metadata used for reporting and search indexing
148-
149142
// content type
150143
if (Astro.props.entry.data.pcx_content_type) {
151144
const contentType = Astro.props.entry.data.pcx_content_type;

src/components/overrides/LastUpdated.astro

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
import type { Props } from "@astrojs/starlight/props";
3+
import Default from "@astrojs/starlight/components/Page.astro";
4+
5+
import { generateDescription, generateTableOfContents } from "~/util/props";
6+
import { getSidebar, flattenSidebar, type SidebarEntry } from "~/util/sidebar";
7+
8+
type Group = Extract<Props["sidebar"][0], { type: "group" }>;
9+
10+
const props = Astro.props;
11+
const data = props.entry.data;
12+
13+
const html = await Astro.slots.render("default");
14+
15+
if (props.toc) {
16+
props.toc.items = await generateTableOfContents(html);
17+
}
18+
19+
if (props.hasSidebar) {
20+
(props.sidebar as unknown as Group) = await getSidebar(Astro);
21+
22+
if (props.pagination) {
23+
const flattened = flattenSidebar(
24+
props.sidebar.entries as unknown as SidebarEntry[],
25+
);
26+
27+
const idx = flattened.findIndex((entry) => entry.isCurrent);
28+
29+
let prev = flattened[idx - 1];
30+
let next = flattened[idx + 1];
31+
32+
if (prev?.attrs["data-group-label"]) {
33+
prev = {
34+
...prev,
35+
label: prev.attrs["data-group-label"],
36+
};
37+
}
38+
39+
if (next?.attrs["data-group-label"]) {
40+
next = {
41+
...next,
42+
label: next.attrs["data-group-label"],
43+
};
44+
}
45+
46+
props.pagination.prev = prev;
47+
props.pagination.next = next;
48+
}
49+
}
50+
51+
if (data.description) {
52+
data.description = await generateDescription({
53+
markdown: data.description,
54+
});
55+
} else {
56+
data.description = await generateDescription({ html });
57+
}
58+
59+
if (data.updated) {
60+
data.lastUpdated = undefined;
61+
}
62+
---
63+
64+
<Default {...Astro.props} set:html={html} />

src/components/overrides/PageSidebar.astro

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/components/overrides/Sidebar.astro

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,9 @@ import type { Props } from "@astrojs/starlight/props";
33
import Default from "@astrojs/starlight/components/Sidebar.astro";
44
55
import { Icon as AstroIcon } from "astro-icon/components";
6-
7-
import { getSidebar, lookupProductTitle } from "~/util/sidebar";
6+
import { lookupProductTitle } from "~/util/sidebar";
87
98
const [product, module] = Astro.url.pathname.split("/").slice(1, -1);
10-
11-
const sidebar = await getSidebar(Astro);
129
---
1310

1411
<a
@@ -26,7 +23,9 @@ const sidebar = await getSidebar(Astro);
2623
</span>
2724
</a>
2825
<!-- @ts-expect-error sidebar props don't match as we add additional things -->
29-
<Default {...Astro.props} sidebar={sidebar.entries}><slot /></Default>
26+
<Default {...Astro.props} sidebar={Astro.props.sidebar.entries}
27+
><slot /></Default
28+
>
3029

3130
<style is:global>
3231
:root {

src/components/overrides/SkipLink.astro

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/util/description.ts

Lines changed: 0 additions & 40 deletions
This file was deleted.

src/util/props.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import type { Props } from "@astrojs/starlight/props";
2+
import { parse } from "node-html-parser";
3+
import he from "he";
4+
import { remark } from "remark";
5+
import strip from "strip-markdown";
6+
import { rehypeExternalLinksOptions } from "~/plugins/rehype/external-links";
7+
8+
export async function generateTableOfContents(
9+
html: string,
10+
): Promise<NonNullable<Props["toc"]>["items"]> {
11+
const items = [
12+
{
13+
text: "Overview",
14+
slug: "_top",
15+
depth: 1,
16+
children: [],
17+
},
18+
];
19+
20+
const dom = parse(html);
21+
const headers = dom.querySelectorAll("h2[id],h3[id]");
22+
23+
if (headers) {
24+
function headerDepth(header: any) {
25+
return Number(header.rawTagName.slice(1));
26+
}
27+
28+
for (const header of headers) {
29+
if (header.id === "footnote-label") continue;
30+
31+
const depth = headerDepth(header);
32+
33+
const title = he.decode(header.innerText);
34+
35+
if (depth === 2) {
36+
items.push({
37+
text: title,
38+
slug: header.id,
39+
depth,
40+
children: [],
41+
});
42+
43+
continue;
44+
}
45+
46+
items.at(-1)?.children.push({
47+
text: title,
48+
slug: header.id,
49+
depth,
50+
children: [],
51+
});
52+
}
53+
}
54+
55+
return items;
56+
}
57+
58+
/**
59+
* Generates a plain-text description for use in the `description` and `og:description` meta tags.
60+
*
61+
* 1. If there is a `description` property in the frontmatter, strip any Markdown tokens and return.
62+
* 2. If there is a `<p>...</p>` element in the HTML, decode any HTML entities and return that.
63+
* 3. Return `undefined` to signal to consumers there is no suitable description.
64+
*/
65+
export async function generateDescription({
66+
html,
67+
markdown,
68+
}: {
69+
html?: string;
70+
markdown?: string;
71+
}) {
72+
let description = undefined;
73+
74+
if (markdown) {
75+
const file = await remark().use(strip).process(markdown);
76+
77+
description = file.toString();
78+
} else if (html) {
79+
const dom = parse(html);
80+
const paragraph = dom.querySelector(":root > p");
81+
82+
if (paragraph) description = he.decode(paragraph.innerText);
83+
}
84+
85+
return description
86+
?.replaceAll(rehypeExternalLinksOptions.content.value, "")
87+
.trim();
88+
}

0 commit comments

Comments
 (0)