diff --git a/site/src/routes/docs/+layout.svelte b/site/src/routes/docs/+layout.svelte index 2ff77a3d2..3950a2fd4 100644 --- a/site/src/routes/docs/+layout.svelte +++ b/site/src/routes/docs/+layout.svelte @@ -1,13 +1,32 @@ - +{#snippet navLinkSnippet(navLink: NormalizedNavLink)} + {#if "items" in navLink} +
  • + {navLink.label} + +
  • + {:else} +
  • + {navLink.label} +
  • + {/if} +{/snippet} +
    {@render children()} diff --git a/site/src/routes/docs/+layout.ts b/site/src/routes/docs/+layout.ts index 826199949..85a4f8bef 100644 --- a/site/src/routes/docs/+layout.ts +++ b/site/src/routes/docs/+layout.ts @@ -1,8 +1,8 @@ -const articles = import.meta.glob("./**/*.md"); +import { navLinks } from "./settings"; +import { normalizeNavLinks } from "./utils"; export function load() { - const paths = Object.keys(articles).map( - (key) => key.slice("./".length, -".md".length) + "/", - ); - return { paths }; + return { + navLinks: normalizeNavLinks(navLinks), + }; } diff --git a/site/src/routes/docs/[...path]/+page.ts b/site/src/routes/docs/[...path]/+page.ts index 15149c71e..eb3d2ab34 100644 --- a/site/src/routes/docs/[...path]/+page.ts +++ b/site/src/routes/docs/[...path]/+page.ts @@ -1,13 +1,20 @@ import { error } from "@sveltejs/kit"; -const articles = import.meta.glob<{ - content: string; - frontmatter: {}; - toc: {}; -}>("../**/*.md"); +const articles = Object.fromEntries( + Object.entries( + import.meta.glob<{ + content: string; + frontmatter: Record; + toc: string; + }>("../**/*.md"), + ).map(([key, fn]) => [key.slice("../".length, -".md".length), fn]), +); export async function load({ params }) { - const article = articles[`../${params.path.slice(0, -"/".length)}.md`]; + const path = params.path.endsWith("/") + ? params.path.slice(0, -1) + : params.path; + const article = articles[path]; if (!article) { error(404, ""); } diff --git a/site/src/routes/docs/settings.ts b/site/src/routes/docs/settings.ts new file mode 100644 index 000000000..429324e44 --- /dev/null +++ b/site/src/routes/docs/settings.ts @@ -0,0 +1,8 @@ +import type { NavLink } from "./utils"; + +export const navLinks: NavLink[] = [ + { + label: "Getting Started", + items: ["getting-started/add-machines"], + }, +]; diff --git a/site/src/routes/docs/utils.ts b/site/src/routes/docs/utils.ts new file mode 100644 index 000000000..a747caa3b --- /dev/null +++ b/site/src/routes/docs/utils.ts @@ -0,0 +1,91 @@ +export const articles = Object.fromEntries( + Object.entries( + import.meta.glob<{ + content: string; + frontmatter: Record; + toc: string; + }>("./**/*.md", { eager: true }), + ).map(([key, fn]) => [key.slice("./".length, -".md".length), fn]), +); + +export type NavLink = + | string + | { + label: string; + items: NavLink[]; + badge?: Badge; + } + | { + label?: string; + slug: string; + badge?: Badge; + }; + +export type NormalizedNavLink = + | { + label: string; + items: NormalizedNavLink[]; + badge?: NormalizedBadge; + } + | { + label: string; + slug: string; + badge?: NormalizedBadge; + }; + +export type Badge = string | NormalizedBadge; + +export type NormalizedBadge = { + text: string; + variant: "caution" | "normal"; +}; + +export function normalizeNavLinks(navLinks: NavLink[]): NormalizedNavLink[] { + return navLinks.map(normalizeNavLink); +} + +export function normalizeNavLink(navLink: NavLink): NormalizedNavLink { + if (typeof navLink === "string") { + const article = articles[navLink]; + if (!article) { + throw new Error(`Doc not found: ${navLink}`); + } + return { + label: article.frontmatter.title, + slug: `/docs/${navLink}`, + }; + } + + if (!("items" in navLink)) { + const article = articles[navLink.slug]; + if (!article) { + throw new Error(`Doc not found: ${navLink}`); + } + return { + ...navLink, + label: navLink.label ?? article.frontmatter.title, + badge: normalizeBadge(navLink.badge), + }; + } + + return { + ...navLink, + badge: normalizeBadge(navLink.badge), + items: navLink.items.map(normalizeNavLink), + }; +} + +export function normalizeBadge( + badge: Badge | undefined, +): NormalizedBadge | undefined { + if (!badge) { + return undefined; + } + if (typeof badge === "string") { + return { + text: badge, + variant: "normal", + }; + } + return badge; +}