@lorenzo_lewis/starlight-utils
Version:
Utilities to use with your 🌟 Starlight site.
99 lines (81 loc) • 3.47 kB
text/typescript
import {
defineRouteMiddleware,
type StarlightRouteData,
} from "@astrojs/starlight/route-data";
import { AstroError } from "astro/errors";
import config from "virtual:starlight-utils/config";
export const onRequest = defineRouteMiddleware((context) => {
// Initialize object
context.locals.starlightUtils = {};
// Logic for navLinks
if (config?.navLinks?.leading) {
const sidebarLabel = config?.navLinks?.leading?.useSidebarLabelled;
if (!sidebarLabel) {
throw new AstroError(
`No sidebar label was specified for the ${JSON.stringify(config?.navLinks?.leading)} entry in the Astro config.`
);
}
const starlightRouteSidebar = context.locals.starlightRoute.sidebar;
const navLinks: typeof starlightRouteSidebar = [];
const filteredSidebar: typeof starlightRouteSidebar = [];
starlightRouteSidebar.forEach((entry) => {
const condition =
entry.label === config?.navLinks?.leading?.useSidebarLabelled;
condition ? navLinks.push(entry) : filteredSidebar.push(entry);
});
if (navLinks.length != 1 || !navLinks[0]) {
throw new AstroError(
`Could not find the sidebar labelled \`${sidebarLabel}\` that was referenced in the Starlight Utils config.`
);
}
if (navLinks[0].type !== "group") {
throw new AstroError(
`\`${navLinks[0].label}\` cannot be used with multi-sidebar.
The sidebar entry specified in the Astro config must be either a group or autogenerated.
See https://starlight.astro.build/guides/sidebar/#groups and https://starlight.astro.build/guides/sidebar/#autogenerated-groups for more details.`
);
}
if (navLinks[0].entries.some((entry) => entry.type !== "link")) {
throw new AstroError(
`Only links can be specified for nav links. No groups or autogenerated types are allowed.`
);
}
// Set navLinks value
context.locals.starlightUtils.navLinks = [...navLinks[0].entries];
// Set the filtered sidebar
context.locals.starlightRoute.sidebar = filteredSidebar;
}
// Logic for multi-sidebar
if (config?.multiSidebar) {
// All entries must be group types
const data = context.locals.starlightRoute.sidebar.map((entry) => {
if (entry.type != "group") {
throw new AstroError(
`\`${entry.label}\` cannot be used with multi-sidebar.
Each top-level \`sidebar\` item in the Starlight config must be either a group or autogenerated.
See https://starlight.astro.build/guides/sidebar/#groups and https://starlight.astro.build/guides/sidebar/#autogenerated-groups for more details.`
);
}
// Recursively check if a group of sidebar entries contains the current page
const findIfIsCurrent = (
entry: StarlightRouteData["sidebar"][number]
): boolean => {
if (entry.type === "link") {
return entry.isCurrent;
}
return entry.entries.some((item) => findIfIsCurrent(item));
};
const isCurrentSidebar = findIfIsCurrent(entry);
return {
isCurrentSidebar,
sidebar: [...entry.entries],
label: entry,
};
});
// If the current page being built isn't contained in a sidebar, then render the first sidebar
if (data[0] && !data.some(({ isCurrentSidebar }) => isCurrentSidebar)) {
data[0].isCurrentSidebar = true;
}
context.locals.starlightUtils.multiSidebar = data;
}
});