Skip to content
Merged
5 changes: 4 additions & 1 deletion _components/Base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ export default function Base(
return (
<>
<div className="ddoc markdown-body">
<comp.Breadcrumbs parts={data.breadcrumbs_ctx.parts} />
<comp.Breadcrumbs
parts={data.breadcrumbs_ctx.parts}
hasSubNav={false}
/>
<main id="content" tabindex={-1}>
{children}
</main>
Expand Down
3 changes: 2 additions & 1 deletion _components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default function (
<data.comp.SidebarNav
sectionData={sectionData}
currentUrl={currentUrl}
apiCategories={data.apiCategories}
/>
</aside>
</>
Expand All @@ -43,7 +44,7 @@ function getSectionData(data: Lume.Data, currentUrl: string) {
const childItems = categoryPanel.categories;

childItems.push({
name: `View all ${categoryPanel.total_symbols} symbols`,
name: `All ${categoryPanel.total_symbols} symbols`,
href: categoryPanel.all_symbols_href,
active: currentUrl.includes("all_symbols"),
});
Expand Down
53 changes: 26 additions & 27 deletions _components/SidebarNav.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,26 @@
// deno-lint-ignore-file no-explicit-any
import ReferenceSidebarNav from "../reference/_components/ReferenceSidebarNav.tsx";

export default function (data: Lume.Data) {
const sectionData = data.sectionData;
const currentUrl = data.currentUrl.replace(/\/$/, "");
const isReference = currentUrl.startsWith("/api/");
const isDenoAPI = currentUrl.startsWith("/api/deno/");

if (isReference) {
return (
<>
{sectionData.map((nav: any) => (
<nav>
<SidebarList>
{nav.items?.map((item: any) => (
<li key={item.href}>
{(isDenoAPI && item.name === "Uncategorized")
? null
: (
<SidebarItem
href={item.href}
title={item.name}
isActive={item.active}
/>
)}
</li>
))}
</SidebarList>
</nav>
))}
</>
);
return <ReferenceSidebarNav {...data} />;
}

// Navigation for rest of site
return (
<>
{sectionData.map((nav: any) => (
<nav>
<nav key={nav.href || nav.title}>
<SidebarCategoryHeading
href={nav.href}
title={nav.title}
isActive={nav.href && nav.href.replace(/\/$/, "") === currentUrl}
isActive={Boolean(
nav.href && nav.href.replace(/\/$/, "") === currentUrl,
)}
/>
{nav.items && Array.isArray(nav.items) && nav.items.length > 0 && (
<SidebarList>
Expand Down Expand Up @@ -85,7 +67,9 @@ export default function (data: Lume.Data) {
);
}

function SidebarList(props: { children: Element; className?: string }) {
function SidebarList(
props: { children: any; className?: string },
) {
return (
<ul
className={`p-0 list-none overflow-y-hidden ${props.className ?? ""}`}
Expand Down Expand Up @@ -124,6 +108,21 @@ function SidebarCategoryHeading(props: {
href?: string;
isActive?: boolean;
}) {
if (props.href) {
return (
<h2 class="block uppercase py-2 pr-4 mt-4 !border-0">
<a
href={props.href}
className={`text-foreground-secondary font-bold leading-none tracking-wide hover:text-primary transition-colors ${
props.isActive ? "text-primary" : ""
}`}
>
{props.title}
</a>
</h2>
);
}

return (
<h2 class="block uppercase py-2 pr-4 mt-4 text-foreground-secondary font-bold leading-[1.2] text-balance tracking-wide !border-0">
{props.title}
Expand Down
26 changes: 7 additions & 19 deletions _components/SubNav.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,26 @@
import { SidebarNav } from "../types.ts";
import { SidebarNavItem } from "../types.ts";

export default function (
{ data, currentUrl }: {
data: Lume.Data;
currentUrl: string;
},
) {
let navData = data.page?.data?.SidebarNav;
const navData = data.page?.data?.SidebarNav;
const isReference = currentUrl.startsWith("/api");
const apiReferenceSubnavItems = [
{
title: "Deno APIs",
href: "/api/deno",
},
{
title: "Web APIs",
href: "/api/web",
},
{
title: "Node APIs",
href: "/api/node",
},
] satisfies SidebarNav;

// We need to hard-code the API Reference subnav, since it's generated elsewhere.
if (isReference && !navData) navData = apiReferenceSubnavItems;
// Don't render SubNav for API reference pages - these will be handled in the sidebar
if (isReference) {
return null;
}

return (
<nav
id="refheader"
class="flex items-center pl-4 bg-header-highlight z-10 h-[var(--subnav-height)] overflow-x-auto xlplus:pl-0"
>
<ul class="flex w-full max-w-7xl mx-auto items-center gap-6">
{navData.map((nav: any) => (
{navData.map((nav: SidebarNavItem) => (
<li key={nav.href}>
<a
className={`whitespace-nowrap text-sm md:text-base p-0 text-gray-800 block relative after:absolute after:bottom-0 after:left-0 after:origin-right after:transition-transform after:scale-x-0 after:block after:w-full after:h-px after:bg-gray-800 hover:after:scale-x-100 hover:after:origin-left ${
Expand Down
46 changes: 46 additions & 0 deletions _config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,52 @@ site.ignore(
// the default layout if no other layout is specified
site.data("layout", "doc.tsx");

// Load API categories data globally
import denoCategories from "./reference_gen/deno-categories.json" with {
type: "json",
};
import webCategories from "./reference_gen/web-categories.json" with {
type: "json",
};
import nodeRewriteMap from "./reference_gen/node-rewrite-map.json" with {
type: "json",
};

const nodeCategories = Object.keys(nodeRewriteMap);

site.data("apiCategories", {
deno: {
title: "Deno APIs",
categories: Object.keys(denoCategories),
descriptions: denoCategories,
getCategoryHref: (categoryName: string) => {
// Special case for I/O -> io
if (categoryName === "I/O") {
return `/api/deno/io`;
}
return `/api/deno/${categoryName.toLowerCase().replace(/\s+/g, "-")}`;
},
},
web: {
title: "Web APIs",
categories: Object.keys(webCategories),
descriptions: webCategories,
getCategoryHref: (categoryName: string) => {
// Special case for I/O -> io
if (categoryName === "I/O") {
return `/api/web/io`;
}
return `/api/web/${categoryName.toLowerCase().replace(/\s+/g, "-")}`;
},
},
node: {
title: "Node APIs",
categories: nodeCategories,
descriptions: {} as Record<string, string>,
getCategoryHref: (categoryName: string) => `/api/node/${categoryName}/`,
},
});

// Do more expensive operations if we're building the full site
if (Deno.env.get("BUILD_TYPE") == "FULL") {
// Use Lume's built in date function to get the last modified date of the file
Expand Down
58 changes: 47 additions & 11 deletions _includes/doc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,48 @@ export default function Doc(data: Lume.Data, helpers: Lume.Helpers) {
}

const isReference = data.url.startsWith("/api/");
const isApiLandingPage = ["/api/deno/", "/api/web/", "/api/node/"].includes(
data.url,
);
const isExamples = data.url.startsWith("/examples/");
const isExampleScript = (data.page.data.content as { type?: string })?.type;
const isLintRule = data.url.startsWith("/lint/rules/");
const isHome = data.url === "/";

const hasBreadcrumbs = !isExamples && !isHome && !isReference;
const hasBreadcrumbs = !isExamples && !isHome &&
!(isReference && !isApiLandingPage);

if (isLintRule) {
file = `/lint/rules/${encodeURIComponent(data.title ?? "")}.md`;
}

function getTocCtx(
d: Lume.Data,
): { document_navigation: unknown; document_navigation_str: string } | null {
const ch: unknown = (d as unknown as { children?: unknown })?.children;
if (ch && typeof ch === "object" && "props" in ch) {
const props: unknown = (ch as { props?: unknown }).props;
if (props && typeof props === "object" && "data" in props) {
const pdata: unknown = (props as { data?: unknown }).data;
if (pdata && typeof pdata === "object" && "toc_ctx" in pdata) {
const toc: unknown = (pdata as { toc_ctx?: unknown }).toc_ctx;
if (
toc && typeof toc === "object" &&
"document_navigation" in toc &&
"document_navigation_str" in toc
) {
const t = toc as {
document_navigation: unknown;
document_navigation_str: string;
};
return t;
}
}
}
}
return null;
}

return (
<>
<main
Expand All @@ -53,7 +84,7 @@ export default function Doc(data: Lume.Data, helpers: Lume.Helpers) {
data-dark-theme="dark"
class="markdown-body mt-4 sm:mt-6"
>
{!isReference && (
{!(isReference && !isApiLandingPage) && (
<h1
dangerouslySetInnerHTML={{
__html: helpers.md(data.title!, true),
Expand All @@ -70,17 +101,22 @@ export default function Doc(data: Lume.Data, helpers: Lume.Helpers) {
{data.children}
</div>
</article>
{!isReference && <data.comp.Feedback file={file} />}
{!(isReference && !isApiLandingPage) && (
<data.comp.Feedback file={file} />
)}
</div>
</main>
{(isReference && data.children.props.data.toc_ctx) && (
<data.comp.RefToc
documentNavigation={data.children.props.data.toc_ctx
.document_navigation}
documentNavigationStr={data.children.props.data.toc_ctx
.document_navigation_str}
/>
)}
{(() => {
const tocCtx = getTocCtx(data);
return isReference && tocCtx
? (
<data.comp.RefToc
documentNavigation={tocCtx.document_navigation}
documentNavigationStr={tocCtx.document_navigation_str}
/>
)
: null;
})()}
</>
);
}
3 changes: 1 addition & 2 deletions _includes/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ export default function Layout(data: Lume.Data) {
const isServicesPage = data.url.startsWith("/deploy") ||
data.url.startsWith("/subhosting") ||
data.url.startsWith("/services");
const hasSubNav = data.page?.data?.SidebarNav?.length ||
data.url.startsWith("/api");
const hasSubNav = isServicesPage;

return (
<html lang="en">
Expand Down
Loading