syntaxai/tdd.md · main · src / a31_docs_nav.ts

a31_docs_nav.ts 94 lines · 2625 bytes raw
// c31 — model: hierarchical site-nav for the GitBook-style docs
// chrome. Pure data: combines the existing per-section registries
// (sama, guides, blog) into one structure the sidebar walks at
// render-time, plus a flat per-section list the prev/next navigator
// uses to compute neighbours.

import { ALL_SAMA, type SamaDiscipline } from "./a31_sama.ts";
import { ALL_GUIDES, type GuideEntry } from "./a31_guides.ts";
import { ALL_POSTS, type BlogEntry } from "./a31_blog.ts";

export interface DocsNavLink {
  href: string;
  label: string;
  // GitHub raw-edit URL for the source markdown, when applicable.
  // null for pages whose body is built inline in c21_app.ts.
  editPath: string | null;
}

export interface DocsNavSection {
  id: "sama" | "guides" | "blog";
  title: string;
  rootHref: string;
  links: DocsNavLink[];
}

const samaLink = (d: SamaDiscipline): DocsNavLink => ({
  href: `/sama/${d.slug}`,
  label: `${d.letter} — ${d.title}`,
  editPath: `content/sama/${d.slug}.md`,
});

const guideLink = (g: GuideEntry): DocsNavLink => ({
  href: `/guides/${g.slug}`,
  label: g.title,
  editPath: `content/guides/${g.slug}.md`,
});

const blogLink = (p: BlogEntry): DocsNavLink => ({
  href: `/blog/${p.slug}`,
  label: p.title,
  editPath: `content/blog/${p.slug}.md`,
});

export const SITE_NAV: DocsNavSection[] = [
  {
    id: "sama",
    title: "SAMA",
    rootHref: "/sama",
    links: [
      ...ALL_SAMA.map(samaLink),
      { href: "/sama/skill", label: "SKILL.md (drop into your agent)", editPath: "content/sama/skill.md" },
      { href: "/sama/verify", label: "verify a public repo", editPath: null },
    ],
  },
  {
    id: "guides",
    title: "Guides",
    rootHref: "/guides",
    links: ALL_GUIDES.map(guideLink),
  },
  {
    id: "blog",
    title: "Blog",
    rootHref: "/blog",
    links: ALL_POSTS.map(blogLink),
  },
];

// Resolve the section + position of a given path. Used by the
// docs layout to select the right sidebar section and to compute
// prev/next neighbours.
export interface ResolvedDocsLocation {
  section: DocsNavSection;
  index: number;
  current: DocsNavLink;
  prev: DocsNavLink | null;
  next: DocsNavLink | null;
}

export const resolveDocsLocation = (path: string): ResolvedDocsLocation | null => {
  for (const section of SITE_NAV) {
    const i = section.links.findIndex((l) => l.href === path);
    if (i === -1) continue;
    return {
      section,
      index: i,
      current: section.links[i]!,
      prev: i > 0 ? section.links[i - 1]! : null,
      next: i < section.links.length - 1 ? section.links[i + 1]! : null,
    };
  }
  return null;
};